diff options
Diffstat (limited to 'gcc/config/arm/arm.md')
-rw-r--r-- | gcc/config/arm/arm.md | 6068 |
1 files changed, 0 insertions, 6068 deletions
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md deleted file mode 100644 index 444e9adcc17..00000000000 --- a/gcc/config/arm/arm.md +++ /dev/null @@ -1,6068 +0,0 @@ -;;- Machine description for Advanced RISC Machines' ARM for GNU compiler -;; Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. -;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) -;; and Martin Simmons (@harleqn.co.uk). -;; More major hacks by Richard Earnshaw (rwe11@cl.cam.ac.uk) - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;; There are patterns in this file to support XFmode arithmetic. -;; Unfortunately RISC iX doesn't work well with these so they are disabled. -;; (See arm.h) - -;; UNSPEC Usage: -;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter, -;; the mode is MODE_FLOAT -;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter, -;; the mode is MODE_FLOAT -;; 2 `push multiple' operation: operand 0 is the first register. Subsequent -;; registers are in parallel (use...) expressions. -;; 3 A symbol that has been treated properly for pic usage, that is, we -;; will add the pic_register value to it before trying to dereference it. -;; Note: sin and cos are no-longer used. - -;; Attributes - -; PROG_MODE attribute is used to determine whether condition codes are -; clobbered by a call insn: they are if in prog32 mode. This is controlled -; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option. -(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode"))) - -; CPU attribute is used to determine whether condition codes are clobbered -; by a call insn: on the arm6 they are if in 32-bit addressing mode; on the -; arm2 and arm3 the condition codes are restored by the return. - -(define_attr "cpu" "arm2,arm3,arm6,arm7" - (const (symbol_ref "arm_cpu_attr"))) - -; Floating Point Unit. If we only have floating point emulation, then there -; is no point in scheduling the floating point insns. (Well, for best -; performance we should try and group them together). - -(define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr"))) - -; LENGTH of an instruction (in bytes) -(define_attr "length" "" (const_int 4)) - -; An assembler sequence may clobber the condition codes without us knowing -(define_asm_attributes - [(set_attr "conds" "clob") - (set_attr "length" "4")]) - -; TYPE attribute is used to detect floating point instructions which, if -; running on a co-processor can run in parallel with other, basic instructions -; If write-buffer scheduling is enabled then it can also be used in the -; scheduling of writes. - -; Classification of each insn -; normal any data instruction that doesn't hit memory or fp regs -; mult a multiply instruction -; block blockage insn, this blocks all functional units -; float a floating point arithmetic operation (subject to expansion) -; fdivx XFmode floating point division -; fdivd DFmode floating point division -; fdivs SFmode floating point division -; fmul Floating point multiply -; ffmul Fast floating point multiply -; farith Floating point arithmetic (4 cycle) -; ffarith Fast floating point arithmetic (2 cycle) -; float_em a floating point arithmetic operation that is normally emulated -; even on a machine with an fpa. -; f_load a floating point load from memory -; f_store a floating point store to memory -; f_mem_r a transfer of a floating point register to a real reg via mem -; r_mem_f the reverse of f_mem_r -; f_2_r fast transfer float to arm (no memory needed) -; r_2_f fast transfer arm to float -; call a subroutine call -; load any load from memory -; store1 store 1 word to memory from arm registers -; store2 store 2 words -; store3 store 3 words -; store4 store 4 words -; -(define_attr "type" - "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4" - (const_string "normal")) - -; condition codes: this one is used by final_prescan_insn to speed up -; conditionalizing instructions. It saves having to scan the rtl to see if -; it uses or alters the condition codes. - -; USE means that the condition codes are used by the insn in the process of -; outputting code, this means (at present) that we can't use the insn in -; inlined branches - -; SET means that the purpose of the insn is to set the condition codes in a -; well defined manner. - -; CLOB means that the condition codes are altered in an undefined manner, if -; they are altered at all - -; JUMP_CLOB is used when the conditions are not defined if a branch is taken, -; but are if the branch wasn't taken; the effect is to limit the branch -; elimination scanning. - -; NOCOND means that the condition codes are neither altered nor affect the -; output of this insn - -(define_attr "conds" "use,set,clob,jump_clob,nocond" - (if_then_else (eq_attr "type" "call") - (if_then_else (eq_attr "prog_mode" "prog32") - (const_string "clob") (const_string "nocond")) - (const_string "nocond"))) - -(define_attr "write_conflict" "no,yes" - (if_then_else (eq_attr "type" - "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load") - (const_string "yes") - (const_string "no"))) - -(define_attr "core_cycles" "single,multi" - (if_then_else (eq_attr "type" - "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith") - (const_string "single") - (const_string "multi"))) - -; The write buffer on some of the arm6 processors is hard to model exactly. -; There is room in the buffer for up to two addresses and up to eight words -; of memory, but the two needn't be split evenly. When writing the two -; addresses are fully pipelined. However, a read from memory that is not -; currently in the cache will block until the writes have completed. -; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so -; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous -; (they aren't allowed to be at present) then there is a startup cost of 1MCLK -; cycle to add as well. - -;; (define_function_unit {name} {num-units} {n-users} {test} -;; {ready-delay} {issue-delay} [{conflict-list}]) -(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") - (eq_attr "type" "fdivx")) 71 69) - -(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") - (eq_attr "type" "fdivd")) 59 57) - -(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") - (eq_attr "type" "fdivs")) 31 29) - -(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") - (eq_attr "type" "fmul")) 9 7) - -(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") - (eq_attr "type" "ffmul")) 6 4) - -(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") - (eq_attr "type" "farith")) 4 2) - -(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") - (eq_attr "type" "ffarith")) 2 2) - -(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") - (eq_attr "type" "r_2_f")) 5 3) - -(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") - (eq_attr "type" "f_2_r")) 1 2) - -;; The fpa10 doesn't really have a memory read unit, but it can start to -;; speculatively execute the instruction in the pipeline, provided the data -;; is already loaded, so pretend reads have a delay of 2 (and that the -;; pipeline is infinite. - -(define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa") - (eq_attr "type" "f_load")) 3 1) - -(define_function_unit "write_buf" 1 2 (eq_attr "type" "store1") 5 3) -(define_function_unit "write_buf" 1 2 (eq_attr "type" "store2") 7 4) -(define_function_unit "write_buf" 1 2 (eq_attr "type" "store3") 9 5) -(define_function_unit "write_buf" 1 2 (eq_attr "type" "store4") 11 6) -(define_function_unit "write_buf" 1 2 (eq_attr "type" "r_mem_f") 5 3) - -;; The write_blockage unit models (partially), the fact that writes will stall -;; until the write buffer empties. - -(define_function_unit "write_blockage" 1 0 (eq_attr "type" "store1") 5 5 - [(eq_attr "write_conflict" "yes")]) -(define_function_unit "write_blockage" 1 0 (eq_attr "type" "store2") 7 7 - [(eq_attr "write_conflict" "yes")]) -(define_function_unit "write_blockage" 1 0 (eq_attr "type" "store3") 9 9 - [(eq_attr "write_conflict" "yes")]) -(define_function_unit "write_blockage" 1 0 (eq_attr "type" "store4") 11 11 - [(eq_attr "write_conflict" "yes")]) -(define_function_unit "write_blockage" 1 0 (eq_attr "type" "r_mem_f") 5 5 - [(eq_attr "write_conflict" "yes")]) -(define_function_unit "write_blockage" 1 0 - (eq_attr "write_conflict" "yes") 1 1) - -(define_function_unit "core" 1 1 (eq_attr "core_cycles" "single") 1 1) - -(define_function_unit "core" 1 1 (eq_attr "type" "load") 2 2) - -(define_function_unit "core" 1 1 (eq_attr "type" "mult") 16 16) - -(define_function_unit "core" 1 1 (eq_attr "type" "store1") 2 2) - -(define_function_unit "core" 1 1 (eq_attr "type" "store2") 3 3) - -(define_function_unit "core" 1 1 (eq_attr "type" "store3") 4 4) - -(define_function_unit "core" 1 1 (eq_attr "type" "store4") 5 5) - -(define_function_unit "core" 1 1 - (and (eq_attr "core_cycles" "multi") - (eq_attr "type" "!mult,load,store2,store3,store4")) 32 32) - - -;; Note: For DImode insns, there is normally no reason why operands should -;; not be in the same register, what we don't want is for something being -;; written to partially overlap something that is an input. - -;; Addition insns. - -(define_insn "adddi3" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0") - (match_operand:DI 2 "s_register_operand" "r,0"))) - (clobber (reg:CC 24))] - "" - "adds\\t%Q0, %Q1, %Q2\;adc\\t%R0, %R1, %R2" -[(set_attr "conds" "clob") - (set_attr "length" "8")]) - -(define_insn "*adddi_sesidi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (plus:DI (sign_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:DI 1 "s_register_operand" "r,0"))) - (clobber (reg:CC 24))] - "" - "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, %2, asr #31" -[(set_attr "conds" "clob") - (set_attr "length" "8")]) - -(define_insn "*adddi_zesidi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (plus:DI (zero_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:DI 1 "s_register_operand" "r,0"))) - (clobber (reg:CC 24))] - "" - "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, #0" -[(set_attr "conds" "clob") - (set_attr "length" "8")]) - -(define_expand "addsi3" - [(set (match_operand:SI 0 "s_register_operand" "") - (plus:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "reg_or_int_operand" "")))] - "" - " - if (GET_CODE (operands[2]) == CONST_INT) - { - arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0], - operands[1], - (reload_in_progress || reload_completed ? 0 - : preserve_subexpressions_p ())); - DONE; - } -") - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (plus:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] - "! (const_ok_for_arm (INTVAL (operands[2])) - || const_ok_for_arm (-INTVAL (operands[2])))" - [(clobber (const_int 0))] - " - arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0], - operands[1], 0); - DONE; -") - -(define_insn "*addsi3_insn" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r") - (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))] - "" - "@ - add%?\\t%0, %1, %2 - sub%?\\t%0, %1, #%n2 - #" -[(set_attr "length" "4,4,16")]) - -(define_insn "*addsi3_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV - (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") - (match_operand:SI 2 "arm_add_operand" "rI,L")) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "@ - add%?s\\t%0, %1, %2 - sub%?s\\t%0, %1, #%n2" -[(set_attr "conds" "set")]) - -(define_insn "*addsi3_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV - (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") - (match_operand:SI 1 "arm_add_operand" "rI,L")) - (const_int 0)))] - "" - "@ - cmn%?\\t%0, %1 - cmp%?\\t%0, #%n1" -[(set_attr "conds" "set")]) - -;; The next four insns work because they compare the result with one of -;; the operands, and we know that the use of the condition code is -;; either GEU or LTU, so we can use the carry flag from the addition -;; instead of doing the compare a second time. -(define_insn "*addsi3_compare_op1" - [(set (reg:CC_C 24) - (compare:CC_C - (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") - (match_operand:SI 2 "arm_add_operand" "rI,L")) - (match_dup 1))) - (set (match_operand:SI 0 "s_register_operand" "=r,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "@ - add%?s\\t%0, %1, %2 - sub%?s\\t%0, %1, #%n2" -[(set_attr "conds" "set")]) - -(define_insn "*addsi3_compare_op2" - [(set (reg:CC_C 24) - (compare:CC_C - (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") - (match_operand:SI 2 "arm_add_operand" "rI,L")) - (match_dup 2))) - (set (match_operand:SI 0 "s_register_operand" "=r,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "@ - add%?s\\t%0, %1, %2 - sub%?s\\t%0, %1, #%n2" -[(set_attr "conds" "set")]) - -(define_insn "*compare_addsi2_op0" - [(set (reg:CC_C 24) - (compare:CC_C - (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") - (match_operand:SI 1 "arm_add_operand" "rI,L")) - (match_dup 0)))] - "" - "@ - cmn%?\\t%0, %1 - cmp%?\\t%0, #%n1" -[(set_attr "conds" "set")]) - -(define_insn "*compare_addsi2_op1" - [(set (reg:CC_C 24) - (compare:CC_C - (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") - (match_operand:SI 1 "arm_add_operand" "rI,L")) - (match_dup 1)))] - "" - "@ - cmn%?\\t%0, %1 - cmp%?\\t%0, #%n1" -[(set_attr "conds" "set")]) - -(define_insn "*addsi3_carryin" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0)) - (plus:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rI"))))] - "" - "adc%?\\t%0, %1, %2" -[(set_attr "conds" "use")]) - -(define_insn "*addsi3_carryin_alt1" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rI")) - (ltu:SI (reg:CC_C 24) (const_int 0))))] - "" - "adc%?\\t%0, %1, %2" -[(set_attr "conds" "use")]) - -(define_insn "*addsi3_carryin_alt2" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0)) - (match_operand:SI 1 "s_register_operand" "r")) - (match_operand:SI 2 "arm_rhs_operand" "rI")))] - "" - "adc%?\\t%0, %1, %2" -[(set_attr "conds" "use")]) - -(define_insn "*addsi3_carryin_alt3" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0)) - (match_operand:SI 2 "arm_rhs_operand" "rI")) - (match_operand:SI 1 "s_register_operand" "r")))] - "" - "adc%?\\t%0, %1, %2" -[(set_attr "conds" "use")]) - -(define_insn "incscc" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (plus:SI (match_operator:SI 2 "comparison_operator" - [(match_operand 3 "cc_register" "") (const_int 0)]) - (match_operand:SI 1 "s_register_operand" "0,?r")))] - "" - "@ - add%d2\\t%0, %1, #1 - mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1" -[(set_attr "conds" "use") - (set_attr "length" "4,8")]) - -; If a constant is too big to fit in a single instruction then the constant -; will be pre-loaded into a register taking at least two insns, we might be -; able to merge it with an add, but it depends on the exact value. - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "const_int_operand" "n")))] - "!(const_ok_for_arm (INTVAL (operands[2])) - || const_ok_for_arm (-INTVAL (operands[2])))" - [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) - (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] - " -{ - unsigned int val = (unsigned) INTVAL (operands[2]); - int i; - unsigned int temp; - - /* this code is similar to the approach followed in movsi, but it must - generate exactly two insns */ - - for (i = 30; i >= 0; i -= 2) - { - if (val & (3 << i)) - { - i -= 6; - if (i < 0) i = 0; - if (const_ok_for_arm (temp = (val & ~(255 << i)))) - { - val &= 255 << i; - break; - } - /* we might be able to do this as (larger number - small number) */ - temp = ((val >> i) & 255) + 1; - if (temp > 255 && i < 24) - { - i += 2; - temp = ((val >> i) & 255) + 1; - } - if (const_ok_for_arm ((temp << i) - val)) - { - i = temp << i; - temp = (unsigned) - (int) (i - val); - val = i; - break; - } - FAIL; - } - } - /* if we got here, we have found a way of doing it in two instructions. - the two constants are in val and temp */ - operands[2] = GEN_INT ((int)val); - operands[3] = GEN_INT ((int)temp); -} -") - -(define_insn "addsf3" - [(set (match_operand:SF 0 "s_register_operand" "=f,f") - (plus:SF (match_operand:SF 1 "s_register_operand" "f,f") - (match_operand:SF 2 "fpu_add_operand" "fG,H")))] - "TARGET_HARD_FLOAT" - "@ - adf%?s\\t%0, %1, %2 - suf%?s\\t%0, %1, #%N2" -[(set_attr "type" "farith")]) - -(define_insn "adddf3" - [(set (match_operand:DF 0 "s_register_operand" "=f,f") - (plus:DF (match_operand:DF 1 "s_register_operand" "f,f") - (match_operand:DF 2 "fpu_add_operand" "fG,H")))] - "TARGET_HARD_FLOAT" - "@ - adf%?d\\t%0, %1, %2 - suf%?d\\t%0, %1, #%N2" -[(set_attr "type" "farith")]) - -(define_insn "*adddf_df_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f,f") - (plus:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f,f")) - (match_operand:DF 2 "fpu_add_operand" "fG,H")))] - "TARGET_HARD_FLOAT" - "@ - adf%?d\\t%0, %1, %2 - suf%?d\\t%0, %1, #%N2" -[(set_attr "type" "farith")]) - -(define_insn "*adddf_df_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (plus:DF (match_operand:DF 1 "s_register_operand" "f") - (float_extend:DF - (match_operand:SF 2 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "adf%?d\\t%0, %1, %2" -[(set_attr "type" "farith")]) - -(define_insn "*adddf_esfdf_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (plus:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f")) - (float_extend:DF - (match_operand:SF 2 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "adf%?d\\t%0, %1, %2" -[(set_attr "type" "farith")]) - -(define_insn "addxf3" - [(set (match_operand:XF 0 "s_register_operand" "=f,f") - (plus:XF (match_operand:XF 1 "s_register_operand" "f,f") - (match_operand:XF 2 "fpu_add_operand" "fG,H")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "@ - adf%?e\\t%0, %1, %2 - suf%?e\\t%0, %1, #%N2" -[(set_attr "type" "farith")]) - -(define_insn "subdi3" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r") - (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0") - (match_operand:DI 2 "s_register_operand" "r,0,0"))) - (clobber (reg:CC 24))] - "" - "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2" -[(set_attr "conds" "clob") - (set_attr "length" "8")]) - -(define_insn "*subdi_di_zesidi" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0") - (zero_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r")))) - (clobber (reg:CC 24))] - "" - "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0" -[(set_attr "conds" "clob") - (set_attr "length" "8")]) - -(define_insn "*subdi_di_sesidi" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (minus:DI (match_operand:DI 1 "s_register_operand" "r,0") - (sign_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r")))) - (clobber (reg:CC 24))] - "" - "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31" -[(set_attr "conds" "clob") - (set_attr "length" "8")]) - -(define_insn "*subdi_zesidi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (minus:DI (zero_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:DI 1 "s_register_operand" "?r,0"))) - (clobber (reg:CC 24))] - "" - "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0" -[(set_attr "conds" "clob") - (set_attr "length" "8")]) - -(define_insn "*subdi_sesidi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (minus:DI (sign_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:DI 1 "s_register_operand" "?r,0"))) - (clobber (reg:CC 24))] - "" - "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31" -[(set_attr "conds" "clob") - (set_attr "length" "8")]) - -(define_insn "*subdi_zesidi_zesidi" - [(set (match_operand:DI 0 "s_register_operand" "=r") - (minus:DI (zero_extend:DI - (match_operand:SI 1 "s_register_operand" "r")) - (zero_extend:DI - (match_operand:SI 2 "s_register_operand" "r")))) - (clobber (reg:CC 24))] - "" - "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1" -[(set_attr "conds" "clob") - (set_attr "length" "8")]) - -(define_expand "subsi3" - [(set (match_operand:SI 0 "s_register_operand" "") - (minus:SI (match_operand:SI 1 "reg_or_int_operand" "") - (match_operand:SI 2 "s_register_operand" "")))] - "" - " - if (GET_CODE (operands[1]) == CONST_INT) - { - arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0], - operands[2], - (reload_in_progress || reload_completed ? 0 - : preserve_subexpressions_p ())); - DONE; - } -") - -(define_insn "*subsi3_insn" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n") - (match_operand:SI 2 "s_register_operand" "r,r")))] - "" - "@ - rsb%?\\t%0, %2, %1 - #" -[(set_attr "length" "4,16")]) - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (minus:SI (match_operand:SI 1 "const_int_operand" "") - (match_operand:SI 2 "s_register_operand" "")))] - "! const_ok_for_arm (INTVAL (operands[1]))" - [(clobber (const_int 0))] - " - arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0], - operands[2], 0); - DONE; -") - -(define_insn "*subsi3_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I") - (match_operand:SI 2 "arm_rhs_operand" "rI,r")) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r,r") - (minus:SI (match_dup 1) (match_dup 2)))] - "" - "@ - sub%?s\\t%0, %1, %2 - rsb%?s\\t%0, %2, %1" -[(set_attr "conds" "set")]) - -(define_insn "decscc" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") - (match_operator:SI 2 "comparison_operator" - [(match_operand 3 "cc_register" "") (const_int 0)])))] - "" - "@ - sub%d2\\t%0, %1, #1 - mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1" -[(set_attr "conds" "use") - (set_attr "length" "*,8")]) - -(define_insn "subsf3" - [(set (match_operand:SF 0 "s_register_operand" "=f,f") - (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") - (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] - "TARGET_HARD_FLOAT" - "@ - suf%?s\\t%0, %1, %2 - rsf%?s\\t%0, %2, %1" -[(set_attr "type" "farith")]) - -(define_insn "subdf3" - [(set (match_operand:DF 0 "s_register_operand" "=f,f") - (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") - (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] - "TARGET_HARD_FLOAT" - "@ - suf%?d\\t%0, %1, %2 - rsf%?d\\t%0, %2, %1" -[(set_attr "type" "farith")]) - -(define_insn "*subdf_esfdf_df" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (minus:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f")) - (match_operand:DF 2 "fpu_rhs_operand" "fG")))] - "TARGET_HARD_FLOAT" - "suf%?d\\t%0, %1, %2" -[(set_attr "type" "farith")]) - -(define_insn "*subdf_df_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f,f") - (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") - (float_extend:DF - (match_operand:SF 2 "s_register_operand" "f,f"))))] - "TARGET_HARD_FLOAT" - "@ - suf%?d\\t%0, %1, %2 - rsf%?d\\t%0, %2, %1" -[(set_attr "type" "farith")]) - -(define_insn "*subdf_esfdf_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (minus:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f")) - (float_extend:DF - (match_operand:SF 2 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "suf%?d\\t%0, %1, %2" -[(set_attr "type" "farith")]) - -(define_insn "subxf3" - [(set (match_operand:XF 0 "s_register_operand" "=f,f") - (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G") - (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "@ - suf%?e\\t%0, %1, %2 - rsf%?e\\t%0, %2, %1" -[(set_attr "type" "farith")]) - -;; Multiplication insns - -;; Use `&' and then `0' to prevent the operands 0 and 1 being the same -(define_insn "mulsi3" - [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") - (mult:SI (match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 1 "s_register_operand" "%?r,0")))] - "" - "mul%?\\t%0, %2, %1" -[(set_attr "type" "mult")]) - -(define_insn "*mulsi3_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (mult:SI - (match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 1 "s_register_operand" "%?r,0")) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=&r,&r") - (mult:SI (match_dup 2) (match_dup 1)))] - "" - "mul%?s\\t%0, %2, %1" -[(set_attr "conds" "set") - (set_attr "type" "mult")]) - -(define_insn "*mulsi_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (mult:SI - (match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 1 "s_register_operand" "%?r,0")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=&r,&r"))] - "" - "mul%?s\\t%0, %2, %1" -[(set_attr "conds" "set") - (set_attr "type" "mult")]) - -;; Unnamed templates to match MLA instruction. - -(define_insn "*mulsi3addsi" - [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r") - (plus:SI - (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r") - (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) - (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))] - "" - "mla%?\\t%0, %2, %1, %3" -[(set_attr "type" "mult")]) - -(define_insn "*mulsi3addsi_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (plus:SI - (mult:SI - (match_operand:SI 2 "s_register_operand" "r,r,r,r") - (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) - (match_operand:SI 3 "s_register_operand" "?r,r,0,0")) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r") - (plus:SI (mult:SI (match_dup 2) (match_dup 1)) - (match_dup 3)))] - "" - "mla%?s\\t%0, %2, %1, %3" -[(set_attr "conds" "set") - (set_attr "type" "mult")]) - -(define_insn "*mulsi3addsi_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (plus:SI - (mult:SI - (match_operand:SI 2 "s_register_operand" "r,r,r,r") - (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) - (match_operand:SI 3 "s_register_operand" "?r,r,0,0")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))] - "" - "mla%?s\\t%0, %2, %1, %3" -[(set_attr "conds" "set") - (set_attr "type" "mult")]) - -(define_insn "mulsidi3" - [(set (match_operand:DI 0 "s_register_operand" "=&r") - (mult:DI (sign_extend:DI - (match_operand:SI 1 "s_register_operand" "%r")) - (sign_extend:DI - (match_operand:SI 2 "s_register_operand" "r"))))] - "arm_fast_multiply" - "smull%?\\t%Q0, %R0, %1, %2" -[(set_attr "type" "mult")]) - -(define_insn "umulsidi3" - [(set (match_operand:DI 0 "s_register_operand" "=&r") - (mult:DI (zero_extend:DI - (match_operand:SI 1 "s_register_operand" "%r")) - (zero_extend:DI - (match_operand:SI 2 "s_register_operand" "r"))))] - "arm_fast_multiply" - "umull%?\\t%Q0, %R0, %1, %2" -[(set_attr "type" "mult")]) - -(define_insn "mulsf3" - [(set (match_operand:SF 0 "s_register_operand" "=f") - (mult:SF (match_operand:SF 1 "s_register_operand" "f") - (match_operand:SF 2 "fpu_rhs_operand" "fG")))] - "TARGET_HARD_FLOAT" - "fml%?s\\t%0, %1, %2" -[(set_attr "type" "ffmul")]) - -(define_insn "muldf3" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (mult:DF (match_operand:DF 1 "s_register_operand" "f") - (match_operand:DF 2 "fpu_rhs_operand" "fG")))] - "TARGET_HARD_FLOAT" - "muf%?d\\t%0, %1, %2" -[(set_attr "type" "fmul")]) - -(define_insn "*muldf_esfdf_df" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (mult:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f")) - (match_operand:DF 2 "fpu_rhs_operand" "fG")))] - "TARGET_HARD_FLOAT" - "muf%?d\\t%0, %1, %2" -[(set_attr "type" "fmul")]) - -(define_insn "*muldf_df_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (mult:DF (match_operand:DF 1 "s_register_operand" "f") - (float_extend:DF - (match_operand:SF 2 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "muf%?d\\t%0, %1, %2" -[(set_attr "type" "fmul")]) - -(define_insn "*muldf_esfdf_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (mult:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f")) - (float_extend:DF - (match_operand:SF 2 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "muf%?d\\t%0, %1, %2" -[(set_attr "type" "fmul")]) - -(define_insn "mulxf3" - [(set (match_operand:XF 0 "s_register_operand" "=f") - (mult:XF (match_operand:XF 1 "s_register_operand" "f") - (match_operand:XF 2 "fpu_rhs_operand" "fG")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "muf%?e\\t%0, %1, %2" -[(set_attr "type" "fmul")]) - -;; Division insns - -(define_insn "divsf3" - [(set (match_operand:SF 0 "s_register_operand" "=f,f") - (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") - (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] - "TARGET_HARD_FLOAT" - "@ - fdv%?s\\t%0, %1, %2 - frd%?s\\t%0, %2, %1" -[(set_attr "type" "fdivs")]) - -(define_insn "divdf3" - [(set (match_operand:DF 0 "s_register_operand" "=f,f") - (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") - (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] - "TARGET_HARD_FLOAT" - "@ - dvf%?d\\t%0, %1, %2 - rdf%?d\\t%0, %2, %1" -[(set_attr "type" "fdivd")]) - -(define_insn "*divdf_esfdf_df" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (div:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f")) - (match_operand:DF 2 "fpu_rhs_operand" "fG")))] - "TARGET_HARD_FLOAT" - "dvf%?d\\t%0, %1, %2" -[(set_attr "type" "fdivd")]) - -(define_insn "*divdf_df_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG") - (float_extend:DF - (match_operand:SF 2 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "rdf%?d\\t%0, %2, %1" -[(set_attr "type" "fdivd")]) - -(define_insn "*divdf_esfdf_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (div:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f")) - (float_extend:DF - (match_operand:SF 2 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "dvf%?d\\t%0, %1, %2" -[(set_attr "type" "fdivd")]) - -(define_insn "divxf3" - [(set (match_operand:XF 0 "s_register_operand" "=f,f") - (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G") - (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "@ - dvf%?e\\t%0, %1, %2 - rdf%?e\\t%0, %2, %1" -[(set_attr "type" "fdivx")]) - -;; Modulo insns - -(define_insn "modsf3" - [(set (match_operand:SF 0 "s_register_operand" "=f") - (mod:SF (match_operand:SF 1 "s_register_operand" "f") - (match_operand:SF 2 "fpu_rhs_operand" "fG")))] - "TARGET_HARD_FLOAT" - "rmf%?s\\t%0, %1, %2" -[(set_attr "type" "fdivs")]) - -(define_insn "moddf3" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (mod:DF (match_operand:DF 1 "s_register_operand" "f") - (match_operand:DF 2 "fpu_rhs_operand" "fG")))] - "TARGET_HARD_FLOAT" - "rmf%?d\\t%0, %1, %2" -[(set_attr "type" "fdivd")]) - -(define_insn "*moddf_esfdf_df" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (mod:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f")) - (match_operand:DF 2 "fpu_rhs_operand" "fG")))] - "TARGET_HARD_FLOAT" - "rmf%?d\\t%0, %1, %2" -[(set_attr "type" "fdivd")]) - -(define_insn "*moddf_df_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (mod:DF (match_operand:DF 1 "s_register_operand" "f") - (float_extend:DF - (match_operand:SF 2 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "rmf%?d\\t%0, %1, %2" -[(set_attr "type" "fdivd")]) - -(define_insn "*moddf_esfdf_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (mod:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f")) - (float_extend:DF - (match_operand:SF 2 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "rmf%?d\\t%0, %1, %2" -[(set_attr "type" "fdivd")]) - -(define_insn "modxf3" - [(set (match_operand:XF 0 "s_register_operand" "=f") - (mod:XF (match_operand:XF 1 "s_register_operand" "f") - (match_operand:XF 2 "fpu_rhs_operand" "fG")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "rmf%?e\\t%0, %1, %2" -[(set_attr "type" "fdivx")]) - -;; Boolean and,ior,xor insns - -(define_insn "anddi3" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (and:DI (match_operand:DI 1 "s_register_operand" "%0,0") - (match_operand:DI 2 "s_register_operand" "r,0")))] - "" - "and%?\\t%Q0, %Q1, %Q2\;and%?\\t%R0, %R1, %R2" -[(set_attr "length" "8")]) - -(define_insn "*anddi_zesidi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (and:DI (zero_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:DI 1 "s_register_operand" "?r,0")))] - "" - "and%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, #0" -[(set_attr "length" "8")]) - -(define_insn "*anddi_sesdi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (and:DI (sign_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:DI 1 "s_register_operand" "?r,0")))] - "" - "and%?\\t%Q0, %Q1, %2\;and%?\\t%R0, %R1, %2, asr #31" -[(set_attr "length" "8")]) - -(define_expand "andsi3" - [(set (match_operand:SI 0 "s_register_operand" "") - (and:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "reg_or_int_operand" "")))] - "" - " - if (GET_CODE (operands[2]) == CONST_INT) - { - arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0], - operands[1], - (reload_in_progress || reload_completed - ? 0 : preserve_subexpressions_p ())); - DONE; - } -") - -(define_insn "*andsi3_insn" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r") - (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))] - "" - "@ - and%?\\t%0, %1, %2 - bic%?\\t%0, %1, #%B2 - #" -[(set_attr "length" "4,4,16")]) - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (and:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] - "! (const_ok_for_arm (INTVAL (operands[2])) - || const_ok_for_arm (~ INTVAL (operands[2])))" - [(clobber (const_int 0))] - " - arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0], - operands[1], 0); - DONE; -") - -(define_insn "*andsi3_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV - (and:SI (match_operand:SI 1 "s_register_operand" "r,r") - (match_operand:SI 2 "arm_not_operand" "rI,K")) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r,r") - (and:SI (match_dup 1) (match_dup 2)))] - "" - "@ - and%?s\\t%0, %1, %2 - bic%?s\\t%0, %1, #%B2" -[(set_attr "conds" "set")]) - -(define_insn "*andsi3_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV - (and:SI (match_operand:SI 0 "s_register_operand" "r,r") - (match_operand:SI 1 "arm_not_operand" "rI,K")) - (const_int 0))) - (clobber (match_scratch:SI 3 "=X,r"))] - "" - "@ - tst%?\\t%0, %1 - bic%?s\\t%3, %0, #%B1" -[(set_attr "conds" "set")]) - -(define_insn "*zeroextractsi_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (zero_extract:SI - (match_operand:SI 0 "s_register_operand" "r") - (match_operand 1 "const_int_operand" "n") - (match_operand 2 "const_int_operand" "n")) - (const_int 0)))] - "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32 - && INTVAL (operands[1]) > 0 - && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8 - && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32" - "* -{ - unsigned int mask = 0; - int cnt = INTVAL (operands[1]); - - while (cnt--) - mask = (mask << 1) | 1; - operands[1] = GEN_INT (mask << INTVAL (operands[2])); - output_asm_insn (\"tst%?\\t%0, %1\", operands); - return \"\"; -} -" -[(set_attr "conds" "set")]) - -(define_insn "*zeroextractqi_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (zero_extract:SI - (match_operand:QI 0 "memory_operand" "m") - (match_operand 1 "const_int_operand" "n") - (match_operand 2 "const_int_operand" "n")) - (const_int 0))) - (clobber (match_scratch:QI 3 "=r"))] - "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 8 - && INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8" - "* -{ - unsigned int mask = 0; - int cnt = INTVAL (operands[1]); - - while (cnt--) - mask = (mask << 1) | 1; - operands[1] = GEN_INT (mask << INTVAL (operands[2])); - output_asm_insn (\"ldr%?b\\t%3, %0\", operands); - output_asm_insn (\"tst%?\\t%3, %1\", operands); - return \"\"; -} -" -[(set_attr "conds" "set") - (set_attr "length" "8")]) - -(define_expand "insv" - [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "") - (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")) - (match_operand:SI 3 "nonmemory_operand" ""))] - "" - " -{ - HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << INTVAL (operands[1])) - 1; - - if (GET_CODE (operands[3]) == CONST_INT) - { - /* Since we are inserting a known constant, we may be able to - reduce the number of bits that we have to clear so that - the mask becomes simple. */ - rtx op1 = gen_reg_rtx (SImode); - HOST_WIDE_INT mask2 = ((mask & ~INTVAL (operands[3])) - << INTVAL (operands[2])); - - emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2))); - emit_insn (gen_iorsi3 (operands[0], op1, - GEN_INT (INTVAL (operands[3]) - << INTVAL (operands[2])))); - } - else if (INTVAL (operands[2]) == 0 - && ! (const_ok_for_arm (mask) - || const_ok_for_arm (~mask))) - { - /* A Trick, since we are setting the bottom bits in the word, - we can shift operand[3] up, operand[0] down, OR them together - and rotate the result back again. This takes 3 insns, and - the third might be mergable into another op. */ - - rtx op0 = gen_reg_rtx (SImode); - rtx op1 = gen_reg_rtx (SImode); - - emit_insn (gen_ashlsi3 (op0, operands[3], - GEN_INT (32 - INTVAL (operands[1])))); - emit_insn (gen_iorsi3 (op1, gen_rtx (LSHIFTRT, SImode, operands[0], - operands[1]), - op0)); - emit_insn (gen_rotlsi3 (operands[0], op1, operands[1])); - } - else if ((INTVAL (operands[1]) + INTVAL (operands[2]) == 32) - && ! (const_ok_for_arm (mask) - || const_ok_for_arm (~mask))) - { - /* Similar trick, but slightly less efficient. */ - - rtx op0 = gen_reg_rtx (SImode); - rtx op1 = gen_reg_rtx (SImode); - - emit_insn (gen_ashlsi3 (op0, operands[3], - GEN_INT (32 - INTVAL (operands[1])))); - emit_insn (gen_ashlsi3 (op1, operands[0], operands[1])); - emit_insn (gen_iorsi3 (operands[0], gen_rtx (LSHIFTRT, SImode, op1, - operands[1]), op0)); - } - else - { - rtx op0 = GEN_INT (mask); - rtx op1 = gen_reg_rtx (SImode); - rtx op2 = gen_reg_rtx (SImode); - - if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask))) - { - rtx tmp = gen_reg_rtx (SImode); - - emit_insn (gen_movsi (tmp, op0)); - op0 = tmp; - } - - emit_insn (gen_andsi3 (op1, operands[3], op0)); - - if (GET_CODE (op0) == CONST_INT - && (const_ok_for_arm (mask << INTVAL (operands[2])) - || const_ok_for_arm (~ (mask << INTVAL (operands[2]))))) - { - op0 = GEN_INT (~(mask << INTVAL (operands[2]))); - emit_insn (gen_andsi3 (op2, operands[0], op0)); - } - else - { - if (GET_CODE (op0) == CONST_INT) - { - rtx tmp = gen_reg_rtx (SImode); - - emit_insn (gen_movsi (tmp, op0)); - op0 = tmp; - } - - if (INTVAL (operands[2]) != 0) - op0 = gen_rtx (ASHIFT, SImode, op0, operands[2]); - emit_insn (gen_andsi_notsi_si (op2, operands[0], op0)); - } - - if (INTVAL (operands[2]) != 0) - op1 = gen_rtx (ASHIFT, SImode, op1, operands[2]); - - emit_insn (gen_iorsi3 (operands[0], op1, op2)); - } - - DONE; -} -") - -;; constants for op 2 will never be given to these patterns. -(define_insn "*anddi_notdi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0")) - (match_operand:DI 1 "s_register_operand" "0,r")))] - "" - "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2" -[(set_attr "length" "8")]) - -(define_insn "*anddi_notzesidi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (and:DI (not:DI (zero_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r"))) - (match_operand:DI 1 "s_register_operand" "0,?r")))] - "" - "@ - bic%?\\t%Q0, %Q1, %2 - bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1" -[(set_attr "length" "4,8")]) - -(define_insn "*anddi_notsesidi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (and:DI (not:DI (sign_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r"))) - (match_operand:DI 1 "s_register_operand" "?r,0")))] - "" - "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31" -[(set_attr "length" "8")]) - -(define_insn "andsi_notsi_si" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) - (match_operand:SI 1 "s_register_operand" "r")))] - "" - "bic%?\\t%0, %1, %2") - -(define_insn "andsi_not_shiftsi_si" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (and:SI (not:SI (match_operator:SI 4 "shift_operator" - [(match_operand:SI 2 "s_register_operand" "r") - (match_operand:SI 3 "arm_rhs_operand" "rM")])) - (match_operand:SI 1 "s_register_operand" "r")))] - "" - "bic%?\\t%0, %1, %2%S4") - -(define_insn "*andsi_notsi_si_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV - (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) - (match_operand:SI 1 "s_register_operand" "r")) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (and:SI (not:SI (match_dup 2)) (match_dup 1)))] - "" - "bic%?s\\t%0, %1, %2" -[(set_attr "conds" "set")]) - -(define_insn "*andsi_notsi_si_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV - (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) - (match_operand:SI 1 "s_register_operand" "r")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "" - "bic%?s\\t%0, %1, %2" -[(set_attr "conds" "set")]) - -(define_insn "iordi3" - [(set (match_operand:DI 0 "s_register_operand" "=&r") - (ior:DI (match_operand:DI 1 "s_register_operand" "%0") - (match_operand:DI 2 "s_register_operand" "r")))] - "" - "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2" -[(set_attr "length" "8")]) - -(define_insn "*iordi_zesidi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (ior:DI (zero_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:DI 1 "s_register_operand" "0,?r")))] - "" - "@ - orr%?\\t%Q0, %Q1, %2 - orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1" -[(set_attr "length" "4,8")]) - -(define_insn "*iordi_sesidi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (ior:DI (sign_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:DI 1 "s_register_operand" "?r,0")))] - "" - "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31" -[(set_attr "length" "8")]) - -(define_expand "iorsi3" - [(set (match_operand:SI 0 "s_register_operand" "") - (ior:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "reg_or_int_operand" "")))] - "" - " - if (GET_CODE (operands[2]) == CONST_INT) - { - arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0], - operands[1], - (reload_in_progress || reload_completed - ? 0 : preserve_subexpressions_p ())); - DONE; - } -") - -(define_insn "*iorsi3_insn" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (ior:SI (match_operand:SI 1 "s_register_operand" "r,r") - (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))] - "" - "@ - orr%?\\t%0, %1, %2 - #" -[(set_attr "length" "4,16")]) - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (ior:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] - "! const_ok_for_arm (INTVAL (operands[2]))" - [(clobber (const_int 0))] - " - arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0], - operands[1], 0); - DONE; -") - -(define_insn "*iorsi3_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") - (match_operand:SI 2 "arm_rhs_operand" "rI")) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (ior:SI (match_dup 1) (match_dup 2)))] - "" - "orr%?s\\t%0, %1, %2" -[(set_attr "conds" "set")]) - -(define_insn "*iorsi3_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") - (match_operand:SI 2 "arm_rhs_operand" "rI")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "" - "orr%?s\\t%0, %1, %2" -[(set_attr "conds" "set")]) - -(define_insn "xordi3" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0") - (match_operand:DI 2 "s_register_operand" "r,0")))] - "" - "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2" -[(set_attr "length" "8")]) - -(define_insn "*xordi_zesidi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (xor:DI (zero_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:DI 1 "s_register_operand" "0,?r")))] - "" - "@ - eor%?\\t%Q0, %Q1, %2 - eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1" -[(set_attr "length" "4,8")]) - -(define_insn "*xordi_sesidi_di" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (xor:DI (sign_extend:DI - (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:DI 1 "s_register_operand" "?r,0")))] - "" - "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31" -[(set_attr "length" "8")]) - -(define_insn "xorsi3" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (xor:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rI")))] - "" - "eor%?\\t%0, %1, %2") - -(define_insn "*xorsi3_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rI")) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (xor:SI (match_dup 1) (match_dup 2)))] - "" - "eor%?s\\t%0, %1, %2" -[(set_attr "conds" "set")]) - -(define_insn "*xorsi3_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r") - (match_operand:SI 1 "arm_rhs_operand" "rI")) - (const_int 0)))] - "" - "teq%?\\t%0, %1" -[(set_attr "conds" "set")]) - -;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), -;; (NOT D) we can sometimes merge the final NOT into one of the following -;; insns - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "=r") - (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r")) - (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI"))) - (match_operand:SI 3 "arm_rhs_operand" "rI"))) - (clobber (match_operand:SI 4 "s_register_operand" "=r"))] - "" - [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2)) - (not:SI (match_dup 3)))) - (set (match_dup 0) (not:SI (match_dup 4)))] - "" -) - -(define_insn "*andsi_iorsi3_notsi" - [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r") - (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0") - (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")) - (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))] - "" - "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3" -[(set_attr "length" "8")]) - - - -;; Minimum and maximum insns - -(define_insn "smaxsi3" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") - (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) - (clobber (reg:CC 24))] - "" - "@ - cmp\\t%1, %2\;movlt\\t%0, %2 - cmp\\t%1, %2\;movge\\t%0, %1 - cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2" -[(set_attr "conds" "clob") - (set_attr "length" "8,8,12")]) - -(define_insn "sminsi3" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") - (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) - (clobber (reg:CC 24))] - "" - "@ - cmp\\t%1, %2\;movge\\t%0, %2 - cmp\\t%1, %2\;movlt\\t%0, %1 - cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2" -[(set_attr "conds" "clob") - (set_attr "length" "8,8,12")]) - -(define_insn "umaxsi3" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") - (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) - (clobber (reg:CC 24))] - "" - "@ - cmp\\t%1, %2\;movcc\\t%0, %2 - cmp\\t%1, %2\;movcs\\t%0, %1 - cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2" -[(set_attr "conds" "clob") - (set_attr "length" "8,8,12")]) - -(define_insn "uminsi3" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") - (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) - (clobber (reg:CC 24))] - "" - "@ - cmp\\t%1, %2\;movcs\\t%0, %2 - cmp\\t%1, %2\;movcc\\t%0, %1 - cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2" -[(set_attr "conds" "clob") - (set_attr "length" "8,8,12")]) - -(define_insn "*store_minmaxsi" - [(set (match_operand:SI 0 "memory_operand" "=m") - (match_operator:SI 3 "minmax_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "s_register_operand" "r")])) - (clobber (reg:CC 24))] - "" - "* - operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1], - operands[2]); - output_asm_insn (\"cmp\\t%1, %2\", operands); - output_asm_insn (\"str%d3\\t%1, %0\", operands); - output_asm_insn (\"str%D3\\t%2, %0\", operands); - return \"\"; -" -[(set_attr "conds" "clob") - (set_attr "length" "12") - (set_attr "type" "store1")]) - -; Reject the frame pointer in operand[1], since reloading this after -; it has been eliminated can cause carnage. -(define_insn "*minmax_arithsi" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (match_operator:SI 4 "shiftable_operator" - [(match_operator:SI 5 "minmax_operator" - [(match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) - (match_operand:SI 1 "s_register_operand" "0,?r")])) - (clobber (reg:CC 24))] - "GET_CODE (operands[1]) != REG - || (REGNO(operands[1]) != FRAME_POINTER_REGNUM - && REGNO(operands[1]) != ARG_POINTER_REGNUM)" - "* -{ - enum rtx_code code = GET_CODE (operands[4]); - - operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2], - operands[3]); - output_asm_insn (\"cmp\\t%2, %3\", operands); - output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands); - if (which_alternative != 0 || operands[3] != const0_rtx - || (code != PLUS && code != MINUS && code != IOR && code != XOR)) - output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands); - return \"\"; -} -" -[(set_attr "conds" "clob") - (set_attr "length" "12")]) - - -;; Shift and rotation insns - -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "s_register_operand" "") - (ashift:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "arm_rhs_operand" "")))] - "" - " - if (GET_CODE (operands[2]) == CONST_INT - && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) - { - emit_insn (gen_movsi (operands[0], const0_rtx)); - DONE; - } -") - -(define_expand "ashrsi3" - [(set (match_operand:SI 0 "s_register_operand" "") - (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "arm_rhs_operand" "")))] - "" - " - if (GET_CODE (operands[2]) == CONST_INT - && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) - operands[2] = GEN_INT (31); -") - -(define_expand "lshrsi3" - [(set (match_operand:SI 0 "s_register_operand" "") - (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "arm_rhs_operand" "")))] - "" - " - if (GET_CODE (operands[2]) == CONST_INT - && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) - { - emit_insn (gen_movsi (operands[0], const0_rtx)); - DONE; - } -") - -(define_expand "rotlsi3" - [(set (match_operand:SI 0 "s_register_operand" "") - (rotatert:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "reg_or_int_operand" "")))] - "" - " - if (GET_CODE (operands[2]) == CONST_INT) - operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32); - else - { - rtx reg = gen_reg_rtx (SImode); - emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2])); - operands[2] = reg; - } -") - -(define_expand "rotrsi3" - [(set (match_operand:SI 0 "s_register_operand" "") - (rotatert:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "arm_rhs_operand" "")))] - "" - " - if (GET_CODE (operands[2]) == CONST_INT - && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) - operands[2] = GEN_INT (INTVAL (operands[2]) % 32); -") - -(define_insn "*shiftsi3" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "reg_or_int_operand" "rM")]))] - "" - "mov%?\\t%0, %1%S3") - -(define_insn "*shiftsi3_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")]) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (match_op_dup 3 [(match_dup 1) (match_dup 2)]))] - "" - "mov%?s\\t%0, %1%S3" -[(set_attr "conds" "set")]) - -(define_insn "*shiftsi3_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")]) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "" - "mov%?s\\t%0, %1%S3" -[(set_attr "conds" "set")]) - -(define_insn "*notsi_shiftsi" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (not:SI (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")])))] - "" - "mvn%?\\t%0, %1%S3") - -(define_insn "*notsi_shiftsi_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")])) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))] - "" - "mvn%?s\\t%0, %1%S3" -[(set_attr "conds" "set")]) - -(define_insn "*not_shiftsi_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")])) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "" - "mvn%?s\\t%0, %1%S3" -[(set_attr "conds" "set")]) - - -;; Unary arithmetic insns - -(define_insn "negdi2" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))] - "" - "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0" -[(set_attr "conds" "clob") - (set_attr "length" "8")]) - -(define_insn "negsi2" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (neg:SI (match_operand:SI 1 "s_register_operand" "r")))] - "" - "rsb%?\\t%0, %1, #0") - -(define_insn "negsf2" - [(set (match_operand:SF 0 "s_register_operand" "=f") - (neg:SF (match_operand:SF 1 "s_register_operand" "f")))] - "TARGET_HARD_FLOAT" - "mnf%?s\\t%0, %1" -[(set_attr "type" "ffarith")]) - -(define_insn "negdf2" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (neg:DF (match_operand:DF 1 "s_register_operand" "f")))] - "TARGET_HARD_FLOAT" - "mnf%?d\\t%0, %1" -[(set_attr "type" "ffarith")]) - -(define_insn "*negdf_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (neg:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "mnf%?d\\t%0, %1" -[(set_attr "type" "ffarith")]) - -(define_insn "negxf2" - [(set (match_operand:XF 0 "s_register_operand" "=f") - (neg:XF (match_operand:XF 1 "s_register_operand" "f")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "mnf%?e\\t%0, %1" -[(set_attr "type" "ffarith")]) - -;; abssi2 doesn't really clobber the condition codes if a different register -;; is being set. To keep things simple, assume during rtl manipulations that -;; it does, but tell the final scan operator the truth. Similarly for -;; (neg (abs...)) - -(define_insn "abssi2" - [(set (match_operand:SI 0 "s_register_operand" "=r,&r") - (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))) - (clobber (reg 24))] - "" - "@ - cmp\\t%0, #0\;rsblt\\t%0, %0, #0 - eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31" -[(set_attr "conds" "clob,*") - (set_attr "length" "8")]) - -(define_insn "*neg_abssi2" - [(set (match_operand:SI 0 "s_register_operand" "=r,&r") - (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))) - (clobber (reg 24))] - "" - "@ - cmp\\t%0, #0\;rsbgt\\t%0, %0, #0 - eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31" -[(set_attr "conds" "clob,*") - (set_attr "length" "8")]) - -(define_insn "abssf2" - [(set (match_operand:SF 0 "s_register_operand" "=f") - (abs:SF (match_operand:SF 1 "s_register_operand" "f")))] - "TARGET_HARD_FLOAT" - "abs%?s\\t%0, %1" -[(set_attr "type" "ffarith")]) - -(define_insn "absdf2" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (abs:DF (match_operand:DF 1 "s_register_operand" "f")))] - "TARGET_HARD_FLOAT" - "abs%?d\\t%0, %1" -[(set_attr "type" "ffarith")]) - -(define_insn "*absdf_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (abs:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "abs%?d\\t%0, %1" -[(set_attr "type" "ffarith")]) - -(define_insn "absxf2" - [(set (match_operand:XF 0 "s_register_operand" "=f") - (abs:XF (match_operand:XF 1 "s_register_operand" "f")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "abs%?e\\t%0, %1" -[(set_attr "type" "ffarith")]) - -(define_insn "sqrtsf2" - [(set (match_operand:SF 0 "s_register_operand" "=f") - (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))] - "TARGET_HARD_FLOAT" - "sqt%?s\\t%0, %1" -[(set_attr "type" "float_em")]) - -(define_insn "sqrtdf2" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))] - "TARGET_HARD_FLOAT" - "sqt%?d\\t%0, %1" -[(set_attr "type" "float_em")]) - -(define_insn "*sqrtdf_esfdf" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (sqrt:DF (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "sqt%?d\\t%0, %1" -[(set_attr "type" "float_em")]) - -(define_insn "sqrtxf2" - [(set (match_operand:XF 0 "s_register_operand" "=f") - (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "sqt%?e\\t%0, %1" -[(set_attr "type" "float_em")]) - -;; SIN COS TAN and family are always emulated, so it's probably better -;; to always call a library function. -;(define_insn "sinsf2" -; [(set (match_operand:SF 0 "s_register_operand" "=f") -; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))] -; "TARGET_HARD_FLOAT" -; "sin%?s\\t%0, %1" -;[(set_attr "type" "float_em")]) -; -;(define_insn "sindf2" -; [(set (match_operand:DF 0 "s_register_operand" "=f") -; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))] -; "TARGET_HARD_FLOAT" -; "sin%?d\\t%0, %1" -;[(set_attr "type" "float_em")]) -; -;(define_insn "*sindf_esfdf" -; [(set (match_operand:DF 0 "s_register_operand" "=f") -; (unspec:DF [(float_extend:DF -; (match_operand:SF 1 "s_register_operand" "f"))] 0))] -; "TARGET_HARD_FLOAT" -; "sin%?d\\t%0, %1" -;[(set_attr "type" "float_em")]) -; -;(define_insn "sinxf2" -; [(set (match_operand:XF 0 "s_register_operand" "=f") -; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))] -; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" -; "sin%?e\\t%0, %1" -;[(set_attr "type" "float_em")]) -; -;(define_insn "cossf2" -; [(set (match_operand:SF 0 "s_register_operand" "=f") -; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))] -; "TARGET_HARD_FLOAT" -; "cos%?s\\t%0, %1" -;[(set_attr "type" "float_em")]) -; -;(define_insn "cosdf2" -; [(set (match_operand:DF 0 "s_register_operand" "=f") -; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))] -; "TARGET_HARD_FLOAT" -; "cos%?d\\t%0, %1" -;[(set_attr "type" "float_em")]) -; -;(define_insn "*cosdf_esfdf" -; [(set (match_operand:DF 0 "s_register_operand" "=f") -; (unspec:DF [(float_extend:DF -; (match_operand:SF 1 "s_register_operand" "f"))] 1))] -; "TARGET_HARD_FLOAT" -; "cos%?d\\t%0, %1" -;[(set_attr "type" "float_em")]) -; -;(define_insn "cosxf2" -; [(set (match_operand:XF 0 "s_register_operand" "=f") -; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))] -; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" -; "cos%?e\\t%0, %1" -;[(set_attr "type" "float_em")]) - -(define_insn "one_cmpldi2" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))] - "" - "mvn%?\\t%Q0, %Q1\;mvn%?\\t%R0, %R1" -[(set_attr "length" "8")]) - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (not:SI (match_operand:SI 1 "s_register_operand" "r")))] - "" - "mvn%?\\t%0, %1") - -(define_insn "*notsi_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r")) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (not:SI (match_dup 1)))] - "" - "mvn%?s\\t%0, %1" -[(set_attr "conds" "set")]) - -(define_insn "*notsi_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "" - "mvn%?s\\t%0, %1" -[(set_attr "conds" "set")]) - -;; Fixed <--> Floating conversion insns - -(define_insn "floatsisf2" - [(set (match_operand:SF 0 "s_register_operand" "=f") - (float:SF (match_operand:SI 1 "s_register_operand" "r")))] - "TARGET_HARD_FLOAT" - "flt%?s\\t%0, %1" -[(set_attr "type" "r_2_f")]) - -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (float:DF (match_operand:SI 1 "s_register_operand" "r")))] - "TARGET_HARD_FLOAT" - "flt%?d\\t%0, %1" -[(set_attr "type" "r_2_f")]) - -(define_insn "floatsixf2" - [(set (match_operand:XF 0 "s_register_operand" "=f") - (float:XF (match_operand:SI 1 "s_register_operand" "r")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "flt%?e\\t%0, %1" -[(set_attr "type" "r_2_f")]) - -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (fix:SI (match_operand:SF 1 "s_register_operand" "f")))] - "TARGET_HARD_FLOAT" - "fix%?z\\t%0, %1" -[(set_attr "type" "f_2_r")]) - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (fix:SI (match_operand:DF 1 "s_register_operand" "f")))] - "TARGET_HARD_FLOAT" - "fix%?z\\t%0, %1" -[(set_attr "type" "f_2_r")]) - -(define_insn "fix_truncxfsi2" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (fix:SI (match_operand:XF 1 "s_register_operand" "f")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "fix%?z\\t%0, %1" -[(set_attr "type" "f_2_r")]) - -;; Truncation insns - -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "s_register_operand" "=f") - (float_truncate:SF - (match_operand:DF 1 "s_register_operand" "f")))] - "TARGET_HARD_FLOAT" - "mvf%?s\\t%0, %1" -[(set_attr "type" "ffarith")]) - -(define_insn "truncxfsf2" - [(set (match_operand:SF 0 "s_register_operand" "=f") - (float_truncate:SF - (match_operand:XF 1 "s_register_operand" "f")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "mvf%?s\\t%0, %1" -[(set_attr "type" "ffarith")]) - -(define_insn "truncxfdf2" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (float_truncate:DF - (match_operand:XF 1 "s_register_operand" "f")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "mvf%?d\\t%0, %1" -[(set_attr "type" "ffarith")]) - -;; Zero and sign extension instructions. - -(define_insn "zero_extendsidi2" - [(set (match_operand:DI 0 "s_register_operand" "=r") - (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] - "" - "* - if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) - output_asm_insn (\"mov%?\\t%Q0, %1\", operands); - return \"mov%?\\t%R0, #0\"; -" -[(set_attr "length" "8")]) - -(define_insn "zero_extendqidi2" - [(set (match_operand:DI 0 "s_register_operand" "=r,r") - (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] - "" - "@ - and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0 - ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0" -[(set_attr "length" "8") - (set_attr "type" "*,load")]) - -(define_insn "extendsidi2" - [(set (match_operand:DI 0 "s_register_operand" "=r") - (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] - "" - "* - if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) - output_asm_insn (\"mov%?\\t%Q0, %1\", operands); - return \"mov%?\\t%R0, %Q0, asr #31\"; -" -[(set_attr "length" "8")]) - -(define_expand "zero_extendhisi2" - [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") - (const_int 16))) - (set (match_operand:SI 0 "s_register_operand" "") - (lshiftrt:SI (match_dup 2) (const_int 16)))] - "" - " -{ - if (arm_arch4 && GET_CODE (operands[1]) == MEM) - { - emit_insn (gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (ZERO_EXTEND, SImode, operands[1]))); - DONE; - } - if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM) - { - emit_insn (gen_movhi_bytes (operands[0], operands[1])); - DONE; - } - if (! s_register_operand (operands[1], HImode)) - operands[1] = copy_to_mode_reg (HImode, operands[1]); - operands[1] = gen_lowpart (SImode, operands[1]); - operands[2] = gen_reg_rtx (SImode); -}") - -(define_insn "*zero_extendhisi_insn" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] - "arm_arch4" - "ldr%?h\\t%0, %1" -[(set_attr "type" "load")]) - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))) - (clobber (match_operand:SI 2 "s_register_operand" ""))] - "! arm_arch4" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))] - " -{ - if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL) - FAIL; -}") - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (match_operator:SI 3 "shiftable_operator" - [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")) - (match_operand:SI 4 "s_register_operand" "")])) - (clobber (match_operand:SI 2 "s_register_operand" ""))] - "! arm_arch4" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 0) - (match_op_dup 3 - [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))] - " -{ - if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL) - FAIL; -}") - -(define_expand "zero_extendqisi2" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (zero_extend:SI - (match_operand:QI 1 "nonimmediate_operand" "r,m")))] - "" - " - if (GET_CODE (operands[1]) != MEM) - { - emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]), - GEN_INT (255))); - DONE; - } -") - -(define_insn "*load_extendqisi" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] - "" - "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2" -[(set_attr "type" "load")]) - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0))) - (clobber (match_operand:SI 2 "s_register_operand" ""))] - "GET_CODE (operands[1]) != MEM" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))] - "") - -(define_insn "*compareqi_eq0" - [(set (reg:CC_Z 24) - (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r") - (const_int 0)))] - "" - "tst\\t%0, #255" -[(set_attr "conds" "set")]) - -(define_expand "extendhisi2" - [(set (match_dup 2) - (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") - (const_int 16))) - (set (match_operand:SI 0 "s_register_operand" "") - (ashiftrt:SI (match_dup 2) - (const_int 16)))] - "" - " -{ - if (arm_arch4 && GET_CODE (operands[1]) == MEM) - { - emit_insn (gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (SIGN_EXTEND, SImode, operands[1]))); - DONE; - } - - if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM) - { - emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); - DONE; - } - if (! s_register_operand (operands[1], HImode)) - operands[1] = copy_to_mode_reg (HImode, operands[1]); - operands[1] = gen_lowpart (SImode, operands[1]); - operands[2] = gen_reg_rtx (SImode); -}") - -(define_expand "extendhisi2_mem" - [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" "")))) - (set (match_dup 3) - (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1))))) - (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24))) - (set (match_operand:SI 0 "" "") - (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))] - "" - " - operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); - operands[2] = gen_reg_rtx (SImode); - operands[3] = gen_reg_rtx (SImode); - operands[6] = gen_reg_rtx (SImode); - - if (BYTES_BIG_ENDIAN) - { - operands[4] = operands[2]; - operands[5] = operands[3]; - } - else - { - operands[4] = operands[3]; - operands[5] = operands[2]; - } -") - -(define_insn "*extendhisi_insn" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] - "arm_arch4" - "ldr%?sh\\t%0, %1" -[(set_attr "type" "load")]) - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))) - (clobber (match_operand:SI 2 "s_register_operand" ""))] - "! arm_arch4" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))] - " -{ - if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL) - FAIL; -}") - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (match_operator:SI 3 "shiftable_operator" - [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")) - (match_operand:SI 4 "s_register_operand" "")])) - (clobber (match_operand:SI 2 "s_register_operand" ""))] - "! arm_arch4" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 0) - (match_op_dup 3 - [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))] - " -{ - if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL) - FAIL; -}") - -(define_expand "extendqihi2" - [(set (match_dup 2) - (ashift:SI (match_operand:QI 1 "general_operand" "") - (const_int 24))) - (set (match_operand:HI 0 "s_register_operand" "") - (ashiftrt:SI (match_dup 2) - (const_int 24)))] - "" - " -{ - if (arm_arch4 && GET_CODE (operands[1]) == MEM) - { - emit_insn (gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (SIGN_EXTEND, HImode, operands[1]))); - DONE; - } - if (! s_register_operand (operands[1], QImode)) - operands[1] = copy_to_mode_reg (QImode, operands[1]); - operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = gen_lowpart (SImode, operands[1]); - operands[2] = gen_reg_rtx (SImode); -}") - -(define_insn "*extendqihi_insn" - [(set (match_operand:HI 0 "s_register_operand" "=r") - (sign_extend:HI (match_operand:QI 1 "memory_operand" "o<>")))] - "arm_arch4" - "ldr%?sb\\t%0, %1" -[(set_attr "type" "load")]) - -(define_expand "extendqisi2" - [(set (match_dup 2) - (ashift:SI (match_operand:QI 1 "s_register_operand" "") - (const_int 24))) - (set (match_operand:SI 0 "s_register_operand" "") - (ashiftrt:SI (match_dup 2) - (const_int 24)))] - "" - " -{ - if (arm_arch4 && GET_CODE (operands[1]) == MEM) - { - emit_insn (gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (SIGN_EXTEND, SImode, operands[1]))); - DONE; - } - if (! s_register_operand (operands[1], QImode)) - operands[1] = copy_to_mode_reg (QImode, operands[1]); - operands[1] = gen_lowpart (SImode, operands[1]); - operands[2] = gen_reg_rtx (SImode); -}") - -(define_insn "*extendqisi_insn" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (sign_extend:SI (match_operand:QI 1 "memory_operand" "o<>")))] - "arm_arch4" - "ldr%?sb\\t%0, %1" -[(set_attr "type" "load")]) - -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "s_register_operand" "=f") - (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))] - "TARGET_HARD_FLOAT" - "mvf%?d\\t%0, %1" -[(set_attr "type" "ffarith")]) - -(define_insn "extendsfxf2" - [(set (match_operand:XF 0 "s_register_operand" "=f") - (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "mvf%?e\\t%0, %1" -[(set_attr "type" "ffarith")]) - -(define_insn "extenddfxf2" - [(set (match_operand:XF 0 "s_register_operand" "=f") - (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "mvf%?e\\t%0, %1" -[(set_attr "type" "ffarith")]) - - -;; Move insns (including loads and stores) - -;; XXX Just some ideas about movti. -;; I don't think these are a good idea on the arm, there just aren't enough -;; registers -;;(define_expand "loadti" -;; [(set (match_operand:TI 0 "s_register_operand" "") -;; (mem:TI (match_operand:SI 1 "address_operand" "")))] -;; "" "") - -;;(define_expand "storeti" -;; [(set (mem:TI (match_operand:TI 0 "address_operand" "")) -;; (match_operand:TI 1 "s_register_operand" ""))] -;; "" "") - -;;(define_expand "movti" -;; [(set (match_operand:TI 0 "general_operand" "") -;; (match_operand:TI 1 "general_operand" ""))] -;; "" -;; " -;;{ -;; rtx insn; -;; -;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) -;; operands[1] = copy_to_reg (operands[1]); -;; if (GET_CODE (operands[0]) == MEM) -;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]); -;; else if (GET_CODE (operands[1]) == MEM) -;; insn = gen_loadti (operands[0], XEXP (operands[1], 0)); -;; else -;; FAIL; -;; -;; emit_insn (insn); -;; DONE; -;;}") - -;; Recognise garbage generated above. - -;;(define_insn "" -;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m") -;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))] -;; "" -;; "* -;; { -;; register mem = (which_alternative < 3); -;; register char *template; -;; -;; operands[mem] = XEXP (operands[mem], 0); -;; switch (which_alternative) -;; { -;; case 0: template = \"ldmdb\\t%1!, %M0\"; break; -;; case 1: template = \"ldmia\\t%1!, %M0\"; break; -;; case 2: template = \"ldmia\\t%1, %M0\"; break; -;; case 3: template = \"stmdb\\t%0!, %M1\"; break; -;; case 4: template = \"stmia\\t%0!, %M1\"; break; -;; case 5: template = \"stmia\\t%0, %M1\"; break; -;; } -;; output_asm_insn (template, operands); -;; return \"\"; -;; }") - - -(define_insn "movdi" - [(set (match_operand:DI 0 "di_operand" "=r,r,o<>") - (match_operand:DI 1 "di_operand" "rIK,mi,r"))] - "" - "* - return (output_move_double (operands)); -" -[(set_attr "length" "8,8,8") - (set_attr "type" "*,load,store2")]) - -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " - /* Everything except mem = const or mem = mem can be done easily */ - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (SImode, operands[1]); - if (GET_CODE (operands[1]) == CONST_INT - && !(const_ok_for_arm (INTVAL (operands[1])) - || const_ok_for_arm (~INTVAL (operands[1])))) - { - arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0], - NULL_RTX, - (reload_in_progress || reload_completed ? 0 - : preserve_subexpressions_p ())); - DONE; - } -") - -(define_insn "*movsi_insn" - [(set (match_operand:SI 0 "general_operand" "=r,r,r,m") - (match_operand:SI 1 "general_operand" "rI,K,mi,r"))] - "register_operand (operands[0], SImode) - || register_operand (operands[1], SImode)" - "@ - mov%?\\t%0, %1 - mvn%?\\t%0, #%B1 - ldr%?\\t%0, %1 - str%?\\t%1, %0" -[(set_attr "type" "*,*,load,store1")]) - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (match_operand:SI 1 "const_int_operand" ""))] - "! (const_ok_for_arm (INTVAL (operands[1])) - || const_ok_for_arm (~INTVAL (operands[1])))" - [(clobber (const_int 0))] - " - arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0], - NULL_RTX, 0); - DONE; -") - -(define_expand "movaddr" - [(set (match_operand:SI 0 "s_register_operand" "") - (match_operand:DI 1 "address_operand" ""))] - "" - "") - -(define_insn "*movaddr_insn" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (match_operand:DI 1 "address_operand" "p"))] - "reload_completed - && (GET_CODE (operands[1]) == LABEL_REF - || (GET_CODE (operands[1]) == CONST - && GET_CODE (XEXP (operands[1], 0)) == PLUS - && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF - && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))" - "adr%?\\t%0, %a1") - -;; If copying one reg to another we can set the condition codes according to -;; its value. Such a move is common after a return from subroutine and the -;; result is being tested against zero. - -(define_insn "*movsi_compare0" - [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r") - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))] - "" - "@ - cmp%?\\t%0, #0 - sub%?s\\t%0, %1, #0" -[(set_attr "conds" "set")]) - -;; Subroutine to store a half word from a register into memory. -;; Operand 0 is the source register (HImode) -;; Operand 1 is the destination address in a register (SImode) - -;; In both this routine and the next, we must be careful not to spill -;; a memory address of reg+large_const into a separate PLUS insn, since this -;; can generate unrecognizable rtl. - -(define_expand "storehi" - [;; store the low byte - (set (mem:QI (match_operand:SI 1 "" "")) (match_dup 3)) - ;; extract the high byte - (set (match_dup 2) - (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) - ;; store the high byte - (set (mem:QI (match_dup 4)) - (subreg:QI (match_dup 2) 0))] ;explicit subreg safe - "" - " -{ - enum rtx_code code = GET_CODE (operands[1]); - - if ((code == PLUS || code == MINUS) - && (GET_CODE (XEXP (operands[1], 1)) == REG - || GET_CODE (XEXP (operands[1], 0)) != REG)) - operands[1] = force_reg (SImode, operands[1]); - operands[4] = plus_constant (operands[1], 1); - operands[3] = gen_lowpart (QImode, operands[0]); - operands[0] = gen_lowpart (SImode, operands[0]); - operands[2] = gen_reg_rtx (SImode); -} -") - -(define_expand "storehi_bigend" - [(set (mem:QI (match_dup 4)) (match_dup 3)) - (set (match_dup 2) - (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) - (set (mem:QI (match_operand 1 "" "")) - (subreg:QI (match_dup 2) 0))] - "" - " -{ - enum rtx_code code = GET_CODE (operands[1]); - if ((code == PLUS || code == MINUS) - && (GET_CODE (XEXP (operands[1], 1)) == REG - || GET_CODE (XEXP (operands[1], 0)) != REG)) - operands[1] = force_reg (SImode, operands[1]); - - operands[4] = plus_constant (operands[1], 1); - operands[3] = gen_lowpart (QImode, operands[0]); - operands[0] = gen_lowpart (SImode, operands[0]); - operands[2] = gen_reg_rtx (SImode); -} -") - -;; Subroutine to store a half word integer constant into memory. -(define_expand "storeinthi" - [(set (mem:QI (match_operand:SI 0 "" "")) - (subreg:QI (match_operand 1 "" "") 0)) - (set (mem:QI (match_dup 3)) (subreg:QI (match_dup 2) 0))] - "" - " -{ - HOST_WIDE_INT value = INTVAL (operands[1]); - enum rtx_code code = GET_CODE (operands[0]); - - if ((code == PLUS || code == MINUS) - && (GET_CODE (XEXP (operands[0], 1)) == REG - || GET_CODE (XEXP (operands[0], 0)) != REG)) - operands[0] = force_reg (SImode, operands[0]); - - operands[1] = gen_reg_rtx (SImode); - if (BYTES_BIG_ENDIAN) - { - emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255))); - if ((value & 255) == ((value >> 8) & 255)) - operands[2] = operands[1]; - else - { - operands[2] = gen_reg_rtx (SImode); - emit_insn (gen_movsi (operands[2], GEN_INT (value & 255))); - } - } - else - { - emit_insn (gen_movsi (operands[1], GEN_INT (value & 255))); - if ((value & 255) == ((value >> 8) & 255)) - operands[2] = operands[1]; - else - { - operands[2] = gen_reg_rtx (SImode); - emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255))); - } - } - - operands[3] = plus_constant (operands[0], 1); -} -") - -(define_expand "storehi_single_op" - [(set (match_operand:HI 0 "memory_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "arm_arch4" - " - if (! s_register_operand (operands[1], HImode)) - operands[1] = copy_to_mode_reg (HImode, operands[1]); -") - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - rtx insn; - - if (! (reload_in_progress || reload_completed)) - { - if (GET_CODE (operands[0]) == MEM) - { - if (arm_arch4) - { - emit_insn (gen_storehi_single_op (operands[0], operands[1])); - DONE; - } - if (GET_CODE (operands[1]) == CONST_INT) - emit_insn (gen_storeinthi (XEXP (operands[0], 0), operands[1])); - else - { - if (GET_CODE (operands[1]) == MEM) - operands[1] = force_reg (HImode, operands[1]); - if (BYTES_BIG_ENDIAN) - emit_insn (gen_storehi_bigend (operands[1], - XEXP (operands[0], 0))); - else - emit_insn (gen_storehi (operands[1], XEXP (operands[0], 0))); - } - DONE; - } - /* Sign extend a constant, and keep it in an SImode reg. */ - else if (GET_CODE (operands[1]) == CONST_INT) - { - rtx reg = gen_reg_rtx (SImode); - HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff; - - /* If the constant is already valid, leave it alone. */ - if (! const_ok_for_arm (val)) - { - /* If setting all the top bits will make the constant - loadable in a single instruction, then set them. - Otherwise, sign extend the number. */ - - if (const_ok_for_arm (~ (val | ~0xffff))) - val |= ~0xffff; - else if (val & 0x8000) - val |= ~0xffff; - } - - emit_insn (gen_movsi (reg, GEN_INT (val))); - operands[1] = gen_rtx (SUBREG, HImode, reg, 0); - } - else if (! arm_arch4) - { - if (GET_CODE (operands[1]) == MEM) - { - if (TARGET_SHORT_BY_BYTES) - { - rtx base; - rtx offset = const0_rtx; - rtx reg = gen_reg_rtx (SImode); - - if ((GET_CODE (base = XEXP (operands[1], 0)) == REG - || (GET_CODE (base) == PLUS - && GET_CODE (offset = XEXP (base, 1)) == CONST_INT - && GET_CODE (base = XEXP (base, 0)) == REG)) - && REGNO_POINTER_ALIGN (REGNO (base)) >= 4) - { - HOST_WIDE_INT new_offset = INTVAL (offset) & ~2; - - emit_insn (gen_movsi (reg, gen_rtx (MEM, SImode, - plus_constant (base, new_offset)))); - if (((INTVAL (offset) & 2) != 0) - ^ (BYTES_BIG_ENDIAN ? 1 : 0)) - { - rtx reg2 = gen_reg_rtx (SImode); - - emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16))); - reg = reg2; - } - } - else - emit_insn (gen_movhi_bytes (reg, operands[1])); - - operands[1] = gen_lowpart (HImode, reg); - } - else if (BYTES_BIG_ENDIAN) - { - rtx base; - rtx offset = const0_rtx; - - if ((GET_CODE (base = XEXP (operands[1], 0)) == REG - || (GET_CODE (base) == PLUS - && GET_CODE (offset = XEXP (base, 1)) == CONST_INT - && GET_CODE (base = XEXP (base, 0)) == REG)) - && REGNO_POINTER_ALIGN (REGNO (base)) >= 4) - { - rtx reg = gen_reg_rtx (SImode); - rtx new_mem; - - if ((INTVAL (offset) & 2) == 2) - { - HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2; - new_mem = gen_rtx (MEM, SImode, - plus_constant (base, new_offset)); - - emit_insn (gen_movsi (reg, new_mem)); - } - else - { - new_mem = gen_rtx (MEM, SImode, - XEXP (operands[1], 0)); - emit_insn (gen_rotated_loadsi (reg, new_mem)); - } - - operands[1] = gen_lowpart (HImode, reg); - } - else - { - emit_insn (gen_movhi_bigend (operands[0], operands[1])); - DONE; - } - } - } - } - } - /* Handle loading a large integer during reload */ - else if (GET_CODE (operands[1]) == CONST_INT - && ! const_ok_for_arm (INTVAL (operands[1])) - && ! const_ok_for_arm (~INTVAL (operands[1]))) - { - /* Writing a constant to memory needs a scratch, which should - be handled with SECONDARY_RELOADs. */ - if (GET_CODE (operands[0]) != REG) - abort (); - - operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0); - emit_insn (gen_movsi (operands[0], operands[1])); - DONE; - } -} -") - -(define_insn "rotated_loadsi" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o") - (const_int 16)))] - "! TARGET_SHORT_BY_BYTES" - "* -{ - rtx ops[2]; - - ops[0] = operands[0]; - ops[1] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 2)); - output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops); - return \"\"; -}" -[(set_attr "type" "load")]) - -(define_expand "movhi_bytes" - [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" "")))) - (set (match_dup 3) - (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1))))) - (set (match_operand:SI 0 "" "") - (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))] - "" - " - operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); - operands[2] = gen_reg_rtx (SImode); - operands[3] = gen_reg_rtx (SImode); - - if (BYTES_BIG_ENDIAN) - { - operands[4] = operands[2]; - operands[5] = operands[3]; - } - else - { - operands[4] = operands[3]; - operands[5] = operands[2]; - } -") - -(define_expand "movhi_bigend" - [(set (match_dup 2) - (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0) - (const_int 16))) - (set (match_dup 3) - (ashiftrt:SI (match_dup 2) (const_int 16))) - (set (match_operand:HI 0 "s_register_operand" "") - (subreg:HI (match_dup 3) 0))] - "" - " - operands[2] = gen_reg_rtx (SImode); - operands[3] = gen_reg_rtx (SImode); -") - -;; Pattern to recognise insn generated default case above - -(define_insn "*movhi_insn_arch4" - [(set (match_operand:HI 0 "general_operand" "=r,r,r,m") - (match_operand:HI 1 "general_operand" "rI,K,m,r"))] - "arm_arch4 - && (GET_CODE (operands[1]) != CONST_INT - || const_ok_for_arm (INTVAL (operands[1])) - || const_ok_for_arm (~INTVAL (operands[1])))" - "@ - mov%?\\t%0, %1\\t%@ movhi - mvn%?\\t%0, #%B1\\t%@ movhi - ldr%?h\\t%0, %1\\t%@ movhi - str%?h\\t%1, %0\\t%@ movhi" -[(set_attr "type" "*,*,load,store1")]) - -(define_insn "*movhi_insn_littleend" - [(set (match_operand:HI 0 "general_operand" "=r,r,r") - (match_operand:HI 1 "general_operand" "rI,K,m"))] - "! arm_arch4 - && ! BYTES_BIG_ENDIAN - && ! TARGET_SHORT_BY_BYTES - && (GET_CODE (operands[1]) != CONST_INT - || const_ok_for_arm (INTVAL (operands[1])) - || const_ok_for_arm (~INTVAL (operands[1])))" - "@ - mov%?\\t%0, %1\\t%@ movhi - mvn%?\\t%0, #%B1\\t%@ movhi - ldr%?\\t%0, %1\\t%@ movhi" -[(set_attr "type" "*,*,load")]) - -(define_insn "*movhi_insn_bigend" - [(set (match_operand:HI 0 "s_register_operand" "=r,r,r") - (match_operand:HI 1 "general_operand" "rI,K,m"))] - "! arm_arch4 - && BYTES_BIG_ENDIAN - && ! TARGET_SHORT_BY_BYTES - && (GET_CODE (operands[1]) != CONST_INT - || const_ok_for_arm (INTVAL (operands[1])) - || const_ok_for_arm (~INTVAL (operands[1])))" - "@ - mov%?\\t%0, %1\\t%@ movhi - mvn%?\\t%0, #%B1\\t%@ movhi - ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16" -[(set_attr "type" "*,*,load") - (set_attr "length" "4,4,8")]) - -(define_insn "*loadhi_si_bigend" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0) - (const_int 16)))] - "BYTES_BIG_ENDIAN - && ! TARGET_SHORT_BY_BYTES" - "ldr%?\\t%0, %1\\t%@ movhi_bigend" -[(set_attr "type" "load")]) - -(define_insn "*movhi_bytes" - [(set (match_operand:HI 0 "s_register_operand" "=r,r") - (match_operand:HI 1 "arm_rhs_operand" "rI,K"))] - "TARGET_SHORT_BY_BYTES" - "@ - mov%?\\t%0, %1\\t%@ movhi - mvn%?\\t%0, #%B1\\t%@ movhi") - - -(define_expand "reload_outhi" - [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o") - (match_operand:HI 1 "s_register_operand" "r") - (match_operand:SI 2 "s_register_operand" "=&r")])] - "" - " - arm_reload_out_hi (operands); - DONE; -") - -(define_expand "reload_inhi" - [(parallel [(match_operand:HI 0 "s_register_operand" "=r") - (match_operand:HI 1 "reload_memory_operand" "o") - (match_operand:SI 2 "s_register_operand" "=&r")])] - "TARGET_SHORT_BY_BYTES" - " - arm_reload_in_hi (operands); - DONE; -") - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " - /* Everything except mem = const or mem = mem can be done easily */ - - if (!(reload_in_progress || reload_completed)) - { - if (GET_CODE (operands[1]) == CONST_INT) - { - rtx reg = gen_reg_rtx (SImode); - - emit_insn (gen_movsi (reg, operands[1])); - operands[1] = gen_rtx (SUBREG, QImode, reg, 0); - } - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (QImode, operands[1]); - } -") - - -(define_insn "*movqi_insn" - [(set (match_operand:QI 0 "general_operand" "=r,r,r,m") - (match_operand:QI 1 "general_operand" "rI,K,m,r"))] - "register_operand (operands[0], QImode) - || register_operand (operands[1], QImode)" - "@ - mov%?\\t%0, %1 - mvn%?\\t%0, #%B1 - ldr%?b\\t%0, %1 - str%?b\\t%1, %0" -[(set_attr "type" "*,*,load,store1")]) - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (SFmode, operands[1]); -") - -(define_insn "*movsf_hard_insn" - [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m") - (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))] - "TARGET_HARD_FLOAT - && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))" - "@ - mvf%?s\\t%0, %1 - mnf%?s\\t%0, #%N1 - ldf%?s\\t%0, %1 - stf%?s\\t%1, %0 - str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4 - stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4 - mov%?\\t%0, %1 - ldr%?\\t%0, %1\\t%@ float - str%?\\t%1, %0\\t%@ float" -[(set_attr "length" "4,4,4,4,8,8,4,4,4") - (set_attr "type" - "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")]) - -;; Exactly the same as above, except that all `f' cases are deleted. -;; This is necessary to prevent reload from ever trying to use a `f' reg -;; when -msoft-float. - -(define_insn "*movsf_soft_insn" - [(set (match_operand:SF 0 "general_operand" "=r,r,m") - (match_operand:SF 1 "general_operand" "r,mE,r"))] - "TARGET_SOFT_FLOAT - && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))" - "@ - mov%?\\t%0, %1 - ldr%?\\t%0, %1\\t%@ float - str%?\\t%1, %0\\t%@ float" -[(set_attr "length" "4,4,4") - (set_attr "type" "*,load,store1")]) - -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (DFmode, operands[1]); -") - -;; Reloading a df mode value stored in integer regs to memory can require a -;; scratch reg. -(define_expand "reload_outdf" - [(match_operand:DF 0 "reload_memory_operand" "=o") - (match_operand:DF 1 "s_register_operand" "r") - (match_operand:SI 2 "s_register_operand" "=&r")] - "" - " -{ - enum rtx_code code = GET_CODE (XEXP (operands[0], 0)); - - if (code == REG) - operands[2] = XEXP (operands[0], 0); - else if (code == POST_INC || code == PRE_DEC) - { - operands[0] = gen_rtx (SUBREG, DImode, operands[0], 0); - operands[1] = gen_rtx (SUBREG, DImode, operands[1], 0); - emit_insn (gen_movdi (operands[0], operands[1])); - DONE; - } - else if (code == PRE_INC) - { - rtx reg = XEXP (XEXP (operands[0], 0), 0); - emit_insn (gen_addsi3 (reg, reg, GEN_INT (8))); - operands[2] = reg; - } - else if (code == POST_DEC) - operands[2] = XEXP (XEXP (operands[0], 0), 0); - else - emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0), - XEXP (XEXP (operands[0], 0), 1))); - - emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, DFmode, operands[2]), - operands[1])); - - if (code == POST_DEC) - emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8))); - - DONE; -} -") - -(define_insn "*movdf_hard_insn" - [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r") - (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))] - "TARGET_HARD_FLOAT - && (GET_CODE (operands[0]) != MEM - || register_operand (operands[1], DFmode))" - "* -{ - rtx ops[3]; - - switch (which_alternative) - { - case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\"; - case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\"; - case 2: case 3: case 4: return output_move_double (operands); - case 5: return \"mvf%?d\\t%0, %1\"; - case 6: return \"mnf%?d\\t%0, #%N1\"; - case 7: return \"ldf%?d\\t%0, %1\"; - case 8: return \"stf%?d\\t%1, %0\"; - case 9: return output_mov_double_fpu_from_arm (operands); - case 10: return output_mov_double_arm_from_fpu (operands); - } -} -" -[(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8") - (set_attr "type" -"load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")]) - -;; Software floating point version. This is essentially the same as movdi. -;; Do not use `f' as a constraint to prevent reload from ever trying to use -;; an `f' reg. - -(define_insn "*movdf_soft_insn" - [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m") - (match_operand:DF 1 "soft_df_operand" "r,mF,r"))] - "TARGET_SOFT_FLOAT" - "* return output_move_double (operands);" -[(set_attr "length" "8,8,8") - (set_attr "type" "*,load,store2")]) - -(define_expand "movxf" - [(set (match_operand:XF 0 "general_operand" "") - (match_operand:XF 1 "general_operand" ""))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "") - -;; Even when the XFmode patterns aren't enabled, we enable this after -;; reloading so that we can push floating point registers in the prologue. - -(define_insn "*movxf_hard_insn" - [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r") - (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))] - "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)" - "* - switch (which_alternative) - { - case 0: return \"mvf%?e\\t%0, %1\"; - case 1: return \"mnf%?e\\t%0, #%N1\"; - case 2: return \"ldf%?e\\t%0, %1\"; - case 3: return \"stf%?e\\t%1, %0\"; - case 4: return output_mov_long_double_fpu_from_arm (operands); - case 5: return output_mov_long_double_arm_from_fpu (operands); - case 6: return output_mov_long_double_arm_from_arm (operands); - } -" -[(set_attr "length" "4,4,4,4,8,8,12") - (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")]) - - -;; load- and store-multiple insns -;; The arm can load/store any set of registers, provided that they are in -;; ascending order; but that is beyond GCC so stick with what it knows. - -(define_expand "load_multiple" - [(match_par_dup 3 [(set (match_operand:SI 0 "" "") - (match_operand:SI 1 "" "")) - (use (match_operand:SI 2 "" ""))])] - "" - " - /* Support only fixed point registers */ - if (GET_CODE (operands[2]) != CONST_INT - || INTVAL (operands[2]) > 14 - || INTVAL (operands[2]) < 2 - || GET_CODE (operands[1]) != MEM - || GET_CODE (operands[0]) != REG - || REGNO (operands[0]) > 14 - || REGNO (operands[0]) + INTVAL (operands[2]) > 15) - FAIL; - - operands[3] - = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]), - force_reg (SImode, XEXP (operands[1], 0)), - TRUE, FALSE); -") - -;; Load multiple with write-back - -(define_insn "*ldmsi_postinc" - [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "s_register_operand" "+r") - (plus:SI (match_dup 1) - (match_operand:SI 2 "const_int_operand" "n"))) - (set (match_operand:SI 3 "s_register_operand" "=r") - (mem:SI (match_dup 1)))])] - "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))" - "* -{ - rtx ops[3]; - int count = XVECLEN (operands[0], 0); - - ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0); - ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1)); - ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2)); - - output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops); - return \"\"; -} -" -[(set_attr "type" "load")]) - -;; Ordinary load multiple - -(define_insn "*ldmsi" - [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "s_register_operand" "=r") - (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])] - "" - "* -{ - rtx ops[3]; - int count = XVECLEN (operands[0], 0); - - ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0); - ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0)); - ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1)); - - output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops); - return \"\"; -} -" -[(set_attr "type" "load")]) - -(define_expand "store_multiple" - [(match_par_dup 3 [(set (match_operand:SI 0 "" "") - (match_operand:SI 1 "" "")) - (use (match_operand:SI 2 "" ""))])] - "" - " - /* Support only fixed point registers */ - if (GET_CODE (operands[2]) != CONST_INT - || INTVAL (operands[2]) > 14 - || INTVAL (operands[2]) < 2 - || GET_CODE (operands[1]) != REG - || GET_CODE (operands[0]) != MEM - || REGNO (operands[1]) > 14 - || REGNO (operands[1]) + INTVAL (operands[2]) > 15) - FAIL; - - operands[3] - = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]), - force_reg (SImode, XEXP (operands[0], 0)), - TRUE, FALSE); -") - -;; Store multiple with write-back - -(define_insn "*stmsi_postinc" - [(match_parallel 0 "store_multiple_operation" - [(set (match_operand:SI 1 "s_register_operand" "+r") - (plus:SI (match_dup 1) - (match_operand:SI 2 "const_int_operand" "n"))) - (set (mem:SI (match_dup 1)) - (match_operand:SI 3 "s_register_operand" "r"))])] - "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))" - "* -{ - rtx ops[3]; - int count = XVECLEN (operands[0], 0); - - ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0); - ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1)); - ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2)); - - output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops); - return \"\"; -} -" -[(set (attr "type") - (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4)) - (const_string "store2") - (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5)) - (const_string "store3")] - (const_string "store4")))]) - -;; Ordinary store multiple - -(define_insn "*stmsi" - [(match_parallel 0 "store_multiple_operation" - [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r")) - (match_operand:SI 1 "s_register_operand" "r"))])] - "" - "* -{ - rtx ops[3]; - int count = XVECLEN (operands[0], 0); - - ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0); - ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0)); - ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1)); - - output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops); - return \"\"; -} -" -[(set (attr "type") - (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3)) - (const_string "store2") - (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4)) - (const_string "store3")] - (const_string "store4")))]) - -;; Move a block of memory if it is word aligned and MORE than 2 words long. -;; We could let this apply for blocks of less than this, but it clobbers so -;; many registers that there is then probably a better way. - -(define_expand "movstrqi" - [(match_operand:BLK 0 "general_operand" "") - (match_operand:BLK 1 "general_operand" "") - (match_operand:SI 2 "const_int_operand" "") - (match_operand:SI 3 "const_int_operand" "")] - "" - " - if (arm_gen_movstrqi (operands)) - DONE; - FAIL; -") - - -;; Comparison and test insns - -(define_expand "cmpsi" - [(match_operand:SI 0 "s_register_operand" "") - (match_operand:SI 1 "arm_add_operand" "")] - "" - " -{ - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; - arm_compare_fp = 0; - DONE; -} -") - -(define_expand "cmpsf" - [(match_operand:SF 0 "s_register_operand" "") - (match_operand:SF 1 "fpu_rhs_operand" "")] - "TARGET_HARD_FLOAT" - " -{ - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; - arm_compare_fp = 1; - DONE; -} -") - -(define_expand "cmpdf" - [(match_operand:DF 0 "s_register_operand" "") - (match_operand:DF 1 "fpu_rhs_operand" "")] - "TARGET_HARD_FLOAT" - " -{ - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; - arm_compare_fp = 1; - DONE; -} -") - -(define_expand "cmpxf" - [(match_operand:XF 0 "s_register_operand" "") - (match_operand:XF 1 "fpu_rhs_operand" "")] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - " -{ - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; - arm_compare_fp = 1; - DONE; -} -") - -(define_insn "*cmpsi_insn" - [(set (reg:CC 24) - (compare:CC (match_operand:SI 0 "s_register_operand" "r,r") - (match_operand:SI 1 "arm_add_operand" "rI,L")))] - "" - "@ - cmp%?\\t%0, %1 - cmn%?\\t%0, #%n1" -[(set_attr "conds" "set")]) - -(define_insn "*cmpsi_shiftsi" - [(set (reg:CC 24) - (compare:CC (match_operand:SI 0 "s_register_operand" "r") - (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")])))] - "" - "cmp%?\\t%0, %1%S3" -[(set_attr "conds" "set")]) - -(define_insn "*cmpsi_shiftsi_swp" - [(set (reg:CC_SWP 24) - (compare:CC_SWP (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "reg_or_int_operand" "rM")]) - (match_operand:SI 0 "s_register_operand" "r")))] - "" - "cmp%?\\t%0, %1%S3" -[(set_attr "conds" "set")]) - -(define_insn "*cmpsi_neg_shiftsi" - [(set (reg:CC 24) - (compare:CC (match_operand:SI 0 "s_register_operand" "r") - (neg:SI (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")]))))] - "" - "cmn%?\\t%0, %1%S3" -[(set_attr "conds" "set")]) - -(define_insn "*cmpsf_insn" - [(set (reg:CCFP 24) - (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f") - (match_operand:SF 1 "fpu_add_operand" "fG,H")))] - "TARGET_HARD_FLOAT" - "@ - cmf%?\\t%0, %1 - cnf%?\\t%0, #%N1" -[(set_attr "conds" "set") - (set_attr "type" "f_2_r")]) - -(define_insn "*cmpdf_insn" - [(set (reg:CCFP 24) - (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f") - (match_operand:DF 1 "fpu_add_operand" "fG,H")))] - "TARGET_HARD_FLOAT" - "@ - cmf%?\\t%0, %1 - cnf%?\\t%0, #%N1" -[(set_attr "conds" "set") - (set_attr "type" "f_2_r")]) - -(define_insn "*cmpesfdf_df" - [(set (reg:CCFP 24) - (compare:CCFP (float_extend:DF - (match_operand:SF 0 "s_register_operand" "f,f")) - (match_operand:DF 1 "fpu_add_operand" "fG,H")))] - "TARGET_HARD_FLOAT" - "@ - cmf%?\\t%0, %1 - cnf%?\\t%0, #%N1" -[(set_attr "conds" "set") - (set_attr "type" "f_2_r")]) - -(define_insn "*cmpdf_esfdf" - [(set (reg:CCFP 24) - (compare:CCFP (match_operand:DF 0 "s_register_operand" "f") - (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "cmf%?\\t%0, %1" -[(set_attr "conds" "set") - (set_attr "type" "f_2_r")]) - -(define_insn "*cmpxf_insn" - [(set (reg:CCFP 24) - (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f") - (match_operand:XF 1 "fpu_add_operand" "fG,H")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "@ - cmf%?\\t%0, %1 - cnf%?\\t%0, #%N1" -[(set_attr "conds" "set") - (set_attr "type" "f_2_r")]) - -(define_insn "*cmpsf_trap" - [(set (reg:CCFPE 24) - (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f") - (match_operand:SF 1 "fpu_add_operand" "fG,H")))] - "TARGET_HARD_FLOAT" - "@ - cmf%?e\\t%0, %1 - cnf%?e\\t%0, #%N1" -[(set_attr "conds" "set") - (set_attr "type" "f_2_r")]) - -(define_insn "*cmpdf_trap" - [(set (reg:CCFPE 24) - (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f") - (match_operand:DF 1 "fpu_add_operand" "fG,H")))] - "TARGET_HARD_FLOAT" - "@ - cmf%?e\\t%0, %1 - cnf%?e\\t%0, #%N1" -[(set_attr "conds" "set") - (set_attr "type" "f_2_r")]) - -(define_insn "*cmp_esfdf_df_trap" - [(set (reg:CCFPE 24) - (compare:CCFPE (float_extend:DF - (match_operand:SF 0 "s_register_operand" "f,f")) - (match_operand:DF 1 "fpu_add_operand" "fG,H")))] - "TARGET_HARD_FLOAT" - "@ - cmf%?e\\t%0, %1 - cnf%?e\\t%0, #%N1" -[(set_attr "conds" "set") - (set_attr "type" "f_2_r")]) - -(define_insn "*cmp_df_esfdf_trap" - [(set (reg:CCFPE 24) - (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f") - (float_extend:DF - (match_operand:SF 1 "s_register_operand" "f"))))] - "TARGET_HARD_FLOAT" - "cmf%?e\\t%0, %1" -[(set_attr "conds" "set") - (set_attr "type" "f_2_r")]) - -(define_insn "*cmpxf_trap" - [(set (reg:CCFPE 24) - (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f") - (match_operand:XF 1 "fpu_add_operand" "fG,H")))] - "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" - "@ - cmf%?e\\t%0, %1 - cnf%?e\\t%0, #%N1" -[(set_attr "conds" "set") - (set_attr "type" "f_2_r")]) - -; This insn allows redundant compares to be removed by cse, nothing should -; ever appear in the output file since (set (reg x) (reg x)) is a no-op that -; is deleted later on. The match_dup will match the mode here, so that -; mode changes of the condition codes aren't lost by this even though we don't -; specify what they are. - -(define_insn "*deleted_compare" - [(set (match_operand 0 "cc_register" "") (match_dup 0))] - "" - "\\t%@ deleted compare" -[(set_attr "conds" "set") - (set_attr "length" "0")]) - - -;; Conditional branch insns - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -;; patterns to match conditional branch insns - -(define_insn "*condbranch" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(match_operand 2 "cc_register" "") (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ - extern int arm_ccfsm_state; - - if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) - { - arm_ccfsm_state += 2; - return \"\"; - } - return \"b%d1\\t%l0\"; -}" -[(set_attr "conds" "use")]) - -(define_insn "*condbranch_reversed" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(match_operand 2 "cc_register" "") (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ - extern int arm_ccfsm_state; - - if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) - { - arm_ccfsm_state += 2; - return \"\"; - } - return \"b%D1\\t%l0\"; -}" -[(set_attr "conds" "use")]) - - -; scc insns - -(define_expand "seq" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "sne" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "sgt" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (gt:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "sle" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (le:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "sge" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (ge:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "slt" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (lt:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "sgtu" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (gtu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "sleu" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (leu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (geu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_expand "sltu" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (ltu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1, - arm_compare_fp); -} -") - -(define_insn "*mov_scc" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (match_operator:SI 1 "comparison_operator" - [(match_operand 2 "cc_register" "") (const_int 0)]))] - "" - "mov%D1\\t%0, #0\;mov%d1\\t%0, #1" -[(set_attr "conds" "use") - (set_attr "length" "8")]) - -(define_insn "*mov_negscc" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (neg:SI (match_operator:SI 1 "comparison_operator" - [(match_operand 2 "cc_register" "") (const_int 0)])))] - "" - "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0" -[(set_attr "conds" "use") - (set_attr "length" "8")]) - -(define_insn "*mov_notscc" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (not:SI (match_operator:SI 1 "comparison_operator" - [(match_operand 2 "cc_register" "") (const_int 0)])))] - "" - "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1" -[(set_attr "conds" "use") - (set_attr "length" "8")]) - - -;; Conditional move insns - -(define_expand "movsicc" - [(set (match_operand:SI 0 "s_register_operand" "") - (if_then_else:SI (match_operand 1 "comparison_operator" "") - (match_operand:SI 2 "arm_not_operand" "") - (match_operand:SI 3 "arm_not_operand" "")))] - "" - " -{ - enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1, - arm_compare_fp); - - operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); -}") - -(define_expand "movsfcc" - [(set (match_operand:SF 0 "s_register_operand" "") - (if_then_else:SF (match_operand 1 "comparison_operator" "") - (match_operand:SF 2 "s_register_operand" "") - (match_operand:SF 3 "nonmemory_operand" "")))] - "" - " -{ - enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1, - arm_compare_fp); - - operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); -}") - -(define_expand "movdfcc" - [(set (match_operand:DF 0 "s_register_operand" "") - (if_then_else:DF (match_operand 1 "comparison_operator" "") - (match_operand:DF 2 "s_register_operand" "") - (match_operand:DF 3 "nonmemory_operand" "")))] - "TARGET_HARD_FLOAT" - " -{ - enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1, - arm_compare_fp); - - operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); -}") - -(define_insn "*movsicc_insn" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r") - (if_then_else:SI - (match_operator 3 "comparison_operator" - [(match_operand 4 "cc_register" "") (const_int 0)]) - (match_operand:SI 1 "arm_not_operand" "0,0,?rI,?rI,K,K") - (match_operand:SI 2 "arm_not_operand" "rI,K,rI,K,rI,K")))] - "" - "@ - mov%D3\\t%0, %2 - mvn%D3\\t%0, #%B2 - mov%d3\\t%0, %1\;mov%D3\\t%0, %2 - mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2 - mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2 - mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2" - [(set_attr "length" "4,4,8,8,8,8") - (set_attr "conds" "use")]) - -(define_insn "*movsfcc_hard_insn" - [(set (match_operand:SF 0 "s_register_operand" "=f,f") - (if_then_else:SF (match_operator 3 "comparison_operator" - [(match_operand 4 "cc_register" "") (const_int 0)]) - (match_operand:SF 1 "s_register_operand" "0,0") - (match_operand:SF 2 "fpu_add_operand" "fG,H")))] - "TARGET_HARD_FLOAT" - "@ - mvf%D3s\\t%0, %2 - mnf%D3s\\t%0, #%N2" - [(set_attr "type" "ffarith") - (set_attr "conds" "use")]) - -(define_insn "*movsfcc_soft_insn" - [(set (match_operand:SF 0 "s_register_operand" "=r") - (if_then_else:SF (match_operator 3 "comparison_operator" - [(match_operand 4 "cc_register" "") (const_int 0)]) - (match_operand:SF 1 "s_register_operand" "0") - (match_operand:SF 2 "s_register_operand" "r")))] - "TARGET_SOFT_FLOAT" - "mov%D3\\t%0, %2" - [(set_attr "conds" "use")]) - -(define_insn "*movdfcc_insn" - [(set (match_operand:DF 0 "s_register_operand" "=f,f") - (if_then_else:DF (match_operator 3 "comparison_operator" - [(match_operand 4 "cc_register" "") (const_int 0)]) - (match_operand:DF 1 "s_register_operand" "0,0") - (match_operand:DF 2 "fpu_add_operand" "fG,H")))] - "TARGET_HARD_FLOAT" - "@ - mvf%D3d\\t%0, %2 - mnf%D3d\\t%0, #%N2" - [(set_attr "type" "ffarith") - (set_attr "conds" "use")]) - -;; Jump and linkage insns - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "* -{ - extern int arm_ccfsm_state; - - if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) - { - arm_ccfsm_state += 2; - return \"\"; - } - return \"b%?\\t%l0\"; -}") - -(define_expand "call" - [(parallel [(call (match_operand 0 "memory_operand" "") - (match_operand 1 "general_operand" "")) - (clobber (reg:SI 14))])] - "" - "") - -(define_insn "*call_reg" - [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) - (match_operand 1 "" "g")) - (clobber (reg:SI 14))] - "" - "* - return output_call (operands); -" -;; length is worst case, normally it is only two -[(set_attr "length" "12") - (set_attr "type" "call")]) - -(define_insn "*call_mem" - [(call (mem:SI (match_operand 0 "memory_operand" "m")) - (match_operand 1 "general_operand" "g")) - (clobber (reg:SI 14))] - "" - "* - return output_call_mem (operands); -" -[(set_attr "length" "12") - (set_attr "type" "call")]) - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "" "=rf") - (call (match_operand 1 "memory_operand" "m") - (match_operand 2 "general_operand" "g"))) - (clobber (reg:SI 14))])] - "" - "") - -(define_insn "*call_value_reg" - [(set (match_operand 0 "" "=rf") - (call (mem:SI (match_operand:SI 1 "s_register_operand" "r")) - (match_operand 2 "general_operand" "g"))) - (clobber (reg:SI 14))] - "" - "* - return output_call (&operands[1]); -" -[(set_attr "length" "12") - (set_attr "type" "call")]) - -(define_insn "*call_value_mem" - [(set (match_operand 0 "" "=rf") - (call (mem:SI (match_operand 1 "memory_operand" "m")) - (match_operand 2 "general_operand" "g"))) - (clobber (reg:SI 14))] - "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))" - "* - return output_call_mem (&operands[1]); -" -[(set_attr "length" "12") - (set_attr "type" "call")]) - -;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses -;; The 'a' causes the operand to be treated as an address, i.e. no '#' output. - -(define_insn "*call_symbol" - [(call (mem:SI (match_operand:SI 0 "" "X")) - (match_operand:SI 1 "general_operand" "g")) - (clobber (reg:SI 14))] - "GET_CODE (operands[0]) == SYMBOL_REF" - "bl%?\\t%a0" -[(set_attr "type" "call")]) - -(define_insn "*call_value_symbol" - [(set (match_operand 0 "s_register_operand" "=rf") - (call (mem:SI (match_operand:SI 1 "" "X")) - (match_operand:SI 2 "general_operand" "g"))) - (clobber (reg:SI 14))] - "GET_CODE(operands[1]) == SYMBOL_REF" - "bl%?\\t%a1" -[(set_attr "type" "call")]) - -;; Often the return insn will be the same as loading from memory, so set attr -(define_insn "return" - [(return)] - "USE_RETURN_INSN" - "* -{ - extern int arm_ccfsm_state; - - if (arm_ccfsm_state == 2) - { - arm_ccfsm_state += 2; - return \"\"; - } - return output_return_instruction (NULL, TRUE, FALSE); -}" -[(set_attr "type" "load")]) - -(define_insn "*cond_return" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "cc_register" "") (const_int 0)]) - (return) - (pc)))] - "USE_RETURN_INSN" - "* -{ - extern int arm_ccfsm_state; - - if (arm_ccfsm_state == 2) - { - arm_ccfsm_state += 2; - return \"\"; - } - return output_return_instruction (operands[0], TRUE, FALSE); -}" -[(set_attr "conds" "use") - (set_attr "type" "load")]) - -(define_insn "*cond_return_inverted" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "cc_register" "") (const_int 0)]) - (pc) - (return)))] - "USE_RETURN_INSN" - "* -{ - extern int arm_ccfsm_state; - - if (arm_ccfsm_state == 2) - { - arm_ccfsm_state += 2; - return \"\"; - } - return output_return_instruction (operands[0], TRUE, TRUE); -}" -[(set_attr "conds" "use") - (set_attr "type" "load")]) - -;; 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 (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)] 0)] - "" - "" -[(set_attr "length" "0") - (set_attr "type" "block")]) - -(define_expand "casesi" - [(match_operand:SI 0 "s_register_operand" "") ; index to jump on - (match_operand:SI 1 "const_int_operand" "") ; lower bound - (match_operand:SI 2 "const_int_operand" "") ; total range - (match_operand:SI 3 "" "") ; table label - (match_operand:SI 4 "" "")] ; Out of range label - "" - " -{ - rtx reg; - if (operands[1] != const0_rtx) - { - reg = gen_reg_rtx (SImode); - emit_insn (gen_addsi3 (reg, operands[0], - GEN_INT (-INTVAL (operands[1])))); - operands[0] = reg; - } - - if (! const_ok_for_arm (INTVAL (operands[2]))) - operands[2] = force_reg (SImode, operands[2]); - - emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3], - operands[4])); - DONE; -}") - -(define_insn "casesi_internal" - [(set (pc) - (if_then_else - (leu (match_operand:SI 0 "s_register_operand" "r") - (match_operand:SI 1 "arm_rhs_operand" "rI")) - (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) - (label_ref (match_operand 2 "" "")))) - (label_ref (match_operand 3 "" ""))))] - "" - "* - if (flag_pic) - return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\"; - return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\"; -" -[(set_attr "conds" "clob") - (set_attr "length" "12")]) - -(define_insn "indirect_jump" - [(set (pc) - (match_operand:SI 0 "s_register_operand" "r"))] - "" - "mov%?\\t%|pc, %0\\t%@ indirect jump") - -(define_insn "*load_indirect_jump" - [(set (pc) - (match_operand:SI 0 "memory_operand" "m"))] - "" - "ldr%?\\t%|pc, %0\\t%@ indirect jump" -[(set_attr "type" "load")]) - -;; Misc insns - -(define_insn "nop" - [(const_int 0)] - "" - "mov%?\\tr0, r0\\t%@ nop") - -;; Patterns to allow combination of arithmetic, cond code and shifts - -(define_insn "*arith_shiftsi" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (match_operator:SI 1 "shiftable_operator" - [(match_operator:SI 3 "shift_operator" - [(match_operand:SI 4 "s_register_operand" "r") - (match_operand:SI 5 "reg_or_int_operand" "rI")]) - (match_operand:SI 2 "s_register_operand" "r")]))] - "" - "%i1%?\\t%0, %2, %4%S3") - -(define_insn "*arith_shiftsi_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" - [(match_operator:SI 3 "shift_operator" - [(match_operand:SI 4 "s_register_operand" "r") - (match_operand:SI 5 "reg_or_int_operand" "rI")]) - (match_operand:SI 2 "s_register_operand" "r")]) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) - (match_dup 2)]))] - "" - "%i1%?s\\t%0, %2, %4%S3" -[(set_attr "conds" "set")]) - -(define_insn "*arith_shiftsi_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" - [(match_operator:SI 3 "shift_operator" - [(match_operand:SI 4 "s_register_operand" "r") - (match_operand:SI 5 "reg_or_int_operand" "rI")]) - (match_operand:SI 2 "s_register_operand" "r")]) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "" - "%i1%?s\\t%0, %2, %4%S3" -[(set_attr "conds" "set")]) - -(define_insn "*sub_shiftsi" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "reg_or_int_operand" "rM")])))] - "" - "sub%?\\t%0, %1, %3%S2") - -(define_insn "*sub_shiftsi_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV - (minus:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "reg_or_int_operand" "rM")])) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) - (match_dup 4)])))] - "" - "sub%?s\\t%0, %1, %3%S2" -[(set_attr "conds" "set")]) - -(define_insn "*sub_shiftsi_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV - (minus:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "reg_or_int_operand" "rM")])) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "" - "sub%?s\\t%0, %1, %3%S2" -[(set_attr "conds" "set")]) - -;; These variants of the above insns can occur if the first operand is the -;; frame pointer and we eliminate that. This is a kludge, but there doesn't -;; seem to be a way around it. Most of the predicates have to be null -;; because the format can be generated part way through reload, so -;; if we don't match it as soon as it becomes available, reload doesn't know -;; how to reload pseudos that haven't got hard registers; the constraints will -;; sort everything out. - -(define_insn "*reload_mulsi3" - [(set (match_operand:SI 0 "" "=&r") - (plus:SI (plus:SI (match_operator:SI 5 "shift_operator" - [(match_operand:SI 3 "" "r") - (match_operand:SI 4 "" "rM")]) - (match_operand:SI 2 "" "r")) - (match_operand:SI 1 "const_int_operand" "n")))] - "reload_in_progress" - "* - output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands); - operands[2] = operands[1]; - operands[1] = operands[0]; - return output_add_immediate (operands); -" -; we have no idea how long the add_immediate is, it could be up to 4. -[(set_attr "length" "20")]) - -(define_insn "*reload_mulsi_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (plus:SI - (plus:SI - (match_operator:SI 5 "shift_operator" - [(match_operand:SI 3 "" "r") - (match_operand:SI 4 "" "rM")]) - (match_operand:SI 1 "" "r")) - (match_operand:SI 2 "const_int_operand" "n")) - (const_int 0))) - (set (match_operand:SI 0 "" "=&r") - (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)]) - (match_dup 1)) - (match_dup 2)))] - "reload_in_progress" - "* - output_add_immediate (operands); - return \"add%?s\\t%0, %0, %3%S5\"; -" -[(set_attr "conds" "set") - (set_attr "length" "20")]) - -(define_insn "*reload_mulsi_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (plus:SI - (plus:SI - (match_operator:SI 5 "shift_operator" - [(match_operand:SI 3 "" "r") - (match_operand:SI 4 "" "rM")]) - (match_operand:SI 1 "" "r")) - (match_operand:SI 2 "const_int_operand" "n")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=&r"))] - "reload_in_progress" - "* - output_add_immediate (operands); - return \"add%?s\\t%0, %0, %3%S5\"; -" -[(set_attr "conds" "set") - (set_attr "length" "20")]) - -;; These are similar, but are needed when the mla pattern contains the -;; eliminated register as operand 3. - -(define_insn "*reload_muladdsi" - [(set (match_operand:SI 0 "" "=&r,&r") - (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r") - (match_operand:SI 2 "" "r,r")) - (match_operand:SI 3 "" "r,r")) - (match_operand:SI 4 "const_int_operand" "n,n")))] - "reload_in_progress" - "* - output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands); - operands[2] = operands[4]; - operands[1] = operands[0]; - return output_add_immediate (operands); -" -[(set_attr "length" "20") - (set_attr "type" "mult")]) - -(define_insn "*reload_muladdsi_compare0" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (plus:SI (plus:SI (mult:SI - (match_operand:SI 3 "" "r") - (match_operand:SI 4 "" "r")) - (match_operand:SI 1 "" "r")) - (match_operand:SI 2 "const_int_operand" "n")) - (const_int 0))) - (set (match_operand:SI 0 "" "=&r") - (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1)) - (match_dup 2)))] - "reload_in_progress" - "* - output_add_immediate (operands); - output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands); - return \"\"; -" -[(set_attr "length" "20") - (set_attr "conds" "set") - (set_attr "type" "mult")]) - -(define_insn "*reload_muladdsi_compare0_scratch" - [(set (reg:CC_NOOV 24) - (compare:CC_NOOV (plus:SI (plus:SI (mult:SI - (match_operand:SI 3 "" "r") - (match_operand:SI 4 "" "r")) - (match_operand:SI 1 "" "r")) - (match_operand:SI 2 "const_int_operand" "n")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=&r"))] - "reload_in_progress" - "* - output_add_immediate (operands); - return \"mla%?s\\t%0, %3, %4, %0\"; -" -[(set_attr "length" "20") - (set_attr "conds" "set") - (set_attr "type" "mult")]) - - - -(define_insn "*and_scc" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (and:SI (match_operator 1 "comparison_operator" - [(match_operand 3 "cc_register" "") (const_int 0)]) - (match_operand:SI 2 "s_register_operand" "r")))] - "" - "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1" -[(set_attr "conds" "use") - (set_attr "length" "8")]) - -(define_insn "*ior_scc" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (ior:SI (match_operator 2 "comparison_operator" - [(match_operand 3 "cc_register" "") (const_int 0)]) - (match_operand:SI 1 "s_register_operand" "0,?r")))] - "" - "@ - orr%d2\\t%0, %1, #1 - mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1" -[(set_attr "conds" "use") - (set_attr "length" "4,8")]) - -(define_insn "*compare_scc" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (match_operator 1 "comparison_operator" - [(match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_add_operand" "rI,L")])) - (clobber (reg 24))] - "" - "* - if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx) - return \"mov\\t%0, %2, lsr #31\"; - - if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx) - return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\"; - - if (GET_CODE (operands[1]) == NE) - { - if (which_alternative == 1) - return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\"; - return \"subs\\t%0, %2, %3\;movne\\t%0, #1\"; - } - if (which_alternative == 1) - output_asm_insn (\"cmn\\t%2, #%n3\", operands); - else - output_asm_insn (\"cmp\\t%2, %3\", operands); - return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; -" -[(set_attr "conds" "clob") - (set_attr "length" "12")]) - -(define_insn "*cond_move" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (if_then_else:SI (match_operator 3 "equality_operator" - [(match_operator 4 "comparison_operator" - [(match_operand 5 "cc_register" "") (const_int 0)]) - (const_int 0)]) - (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") - (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))] - "" - "* - if (GET_CODE (operands[3]) == NE) - { - if (which_alternative != 1) - output_asm_insn (\"mov%D4\\t%0, %2\", operands); - if (which_alternative != 0) - output_asm_insn (\"mov%d4\\t%0, %1\", operands); - return \"\"; - } - if (which_alternative != 0) - output_asm_insn (\"mov%D4\\t%0, %1\", operands); - if (which_alternative != 1) - output_asm_insn (\"mov%d4\\t%0, %2\", operands); - return \"\"; -" -[(set_attr "conds" "use") - (set_attr "length" "4,4,8")]) - -(define_insn "*cond_arith" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (match_operator:SI 5 "shiftable_operator" - [(match_operator:SI 4 "comparison_operator" - [(match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) - (match_operand:SI 1 "s_register_operand" "0,?r")])) - (clobber (reg 24))] - "" - "* - if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) - return \"%i5\\t%0, %1, %2, lsr #31\"; - - output_asm_insn (\"cmp\\t%2, %3\", operands); - if (GET_CODE (operands[5]) == AND) - output_asm_insn (\"mov%D4\\t%0, #0\", operands); - else if (GET_CODE (operands[5]) == MINUS) - output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands); - else if (which_alternative != 0) - output_asm_insn (\"mov%D4\\t%0, %1\", operands); - return \"%i5%d4\\t%0, %1, #1\"; -" -[(set_attr "conds" "clob") - (set_attr "length" "12")]) - -(define_insn "*cond_sub" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") - (match_operator:SI 4 "comparison_operator" - [(match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) - (clobber (reg 24))] - "" - "* - output_asm_insn (\"cmp\\t%2, %3\", operands); - if (which_alternative != 0) - output_asm_insn (\"mov%D4\\t%0, %1\", operands); - return \"sub%d4\\t%0, %1, #1\"; -" -[(set_attr "conds" "clob") - (set_attr "length" "8,12")]) - -(define_insn "*cmp_ite0" - [(set (match_operand 6 "dominant_cc_register" "") - (compare - (if_then_else:SI - (match_operator 4 "comparison_operator" - [(match_operand:SI 0 "s_register_operand" "r,r,r,r") - (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) - (match_operator:SI 5 "comparison_operator" - [(match_operand:SI 2 "s_register_operand" "r,r,r,r") - (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) - (const_int 0)) - (const_int 0)))] - "" - "* -{ - char* opcodes[4][2] = - { - {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, - {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, - {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, - {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", - \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} - }; - int swap = - comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); - - return opcodes[which_alternative][swap]; -} -" -[(set_attr "conds" "set") - (set_attr "length" "8")]) - -(define_insn "*cmp_ite1" - [(set (match_operand 6 "dominant_cc_register" "") - (compare - (if_then_else:SI - (match_operator 4 "comparison_operator" - [(match_operand:SI 0 "s_register_operand" "r,r,r,r") - (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) - (match_operator:SI 5 "comparison_operator" - [(match_operand:SI 2 "s_register_operand" "r,r,r,r") - (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) - (const_int 1)) - (const_int 0)))] - "" - "* -{ - char* opcodes[4][2] = - { - {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, - {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, - {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, - {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\", - \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} - }; - int swap = - comparison_dominates_p (GET_CODE (operands[5]), - reverse_condition (GET_CODE (operands[4]))); - - return opcodes[which_alternative][swap]; -} -" -[(set_attr "conds" "set") - (set_attr "length" "8")]) - -(define_insn "*negscc" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (neg:SI (match_operator 3 "comparison_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rI")]))) - (clobber (reg 24))] - "" - "* - if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx) - return \"mov\\t%0, %1, asr #31\"; - - if (GET_CODE (operands[3]) == NE) - return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\"; - - if (GET_CODE (operands[3]) == GT) - return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\"; - - output_asm_insn (\"cmp\\t%1, %2\", operands); - output_asm_insn (\"mov%D3\\t%0, #0\", operands); - return \"mvn%d3\\t%0, #0\"; -" -[(set_attr "conds" "clob") - (set_attr "length" "12")]) - -(define_insn "movcond" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (if_then_else:SI - (match_operator 5 "comparison_operator" - [(match_operand:SI 3 "s_register_operand" "r,r,r") - (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")]) - (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") - (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) - (clobber (reg 24))] - "" - "* - if (GET_CODE (operands[5]) == LT - && (operands[4] == const0_rtx)) - { - if (which_alternative != 1 && GET_CODE (operands[1]) == REG) - { - if (operands[2] == const0_rtx) - return \"and\\t%0, %1, %3, asr #31\"; - return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\"; - } - else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) - { - if (operands[1] == const0_rtx) - return \"bic\\t%0, %2, %3, asr #31\"; - return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\"; - } - /* The only case that falls through to here is when both ops 1 & 2 - are constants */ - } - - if (GET_CODE (operands[5]) == GE - && (operands[4] == const0_rtx)) - { - if (which_alternative != 1 && GET_CODE (operands[1]) == REG) - { - if (operands[2] == const0_rtx) - return \"bic\\t%0, %1, %3, asr #31\"; - return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\"; - } - else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) - { - if (operands[1] == const0_rtx) - return \"and\\t%0, %2, %3, asr #31\"; - return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\"; - } - /* The only case that falls through to here is when both ops 1 & 2 - are constants */ - } - if (GET_CODE (operands[4]) == CONST_INT - && !const_ok_for_arm (INTVAL (operands[4]))) - output_asm_insn (\"cmn\\t%3, #%n4\", operands); - else - output_asm_insn (\"cmp\\t%3, %4\", operands); - if (which_alternative != 0) - output_asm_insn (\"mov%d5\\t%0, %1\", operands); - if (which_alternative != 1) - output_asm_insn (\"mov%D5\\t%0, %2\", operands); - return \"\"; -" -[(set_attr "conds" "clob") - (set_attr "length" "8,8,12")]) - -(define_insn "*ifcompare_plus_move" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (if_then_else:SI (match_operator 6 "comparison_operator" - [(match_operand:SI 4 "s_register_operand" "r,r") - (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) - (plus:SI - (match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_add_operand" "rIL,rIL")) - (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm"))) - (clobber (reg 24))] - "" - "#" -[(set_attr "conds" "clob") - (set_attr "length" "8,12")]) - -(define_insn "*if_plus_move" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r") - (if_then_else:SI - (match_operator 4 "comparison_operator" - [(match_operand 5 "cc_register" "") (const_int 0)]) - (plus:SI - (match_operand:SI 2 "s_register_operand" "r,r,r,r,r,r") - (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L,rI,L")) - (match_operand:SI 1 "arm_rhsm_operand" "0,0,?rI,?rI,m,m")))] - "" - "@ - add%d4\\t%0, %2, %3 - sub%d4\\t%0, %2, #%n3 - add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1 - sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1 - add%d4\\t%0, %2, %3\;ldr%D4\\t%0, %1 - sub%d4\\t%0, %2, #%n3\;ldr%D4\\t%0, %1" -[(set_attr "conds" "use") - (set_attr "length" "4,4,8,8,8,8") - (set_attr "type" "*,*,*,*,load,load")]) - -(define_insn "*ifcompare_move_plus" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (if_then_else:SI (match_operator 6 "comparison_operator" - [(match_operand:SI 4 "s_register_operand" "r,r") - (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) - (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm") - (plus:SI - (match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_add_operand" "rIL,rIL")))) - (clobber (reg 24))] - "" - "#" -[(set_attr "conds" "clob") - (set_attr "length" "8,12")]) - -(define_insn "*if_move_plus" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r") - (if_then_else:SI - (match_operator 4 "comparison_operator" - [(match_operand 5 "cc_register" "") (const_int 0)]) - (match_operand:SI 1 "arm_rhsm_operand" "0,0,?rI,?rI,m,m") - (plus:SI - (match_operand:SI 2 "s_register_operand" "r,r,r,r,r,r") - (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L,rI,L"))))] - "" - "@ - add%D4\\t%0, %2, %3 - sub%D4\\t%0, %2, #%n3 - add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1 - sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1 - add%D4\\t%0, %2, %3\;ldr%d4\\t%0, %1 - sub%D4\\t%0, %2, #%n3\;ldr%d4\\t%0, %1" -[(set_attr "conds" "use") - (set_attr "length" "4,4,8,8,8,8") - (set_attr "type" "*,*,*,*,load,load")]) - -(define_insn "*ifcompare_arith_arith" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (if_then_else:SI (match_operator 9 "comparison_operator" - [(match_operand:SI 5 "s_register_operand" "r") - (match_operand:SI 6 "arm_add_operand" "rIL")]) - (match_operator:SI 8 "shiftable_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rI")]) - (match_operator:SI 7 "shiftable_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "arm_rhs_operand" "rI")]))) - (clobber (reg 24))] - "" - "#" -[(set_attr "conds" "clob") - (set_attr "length" "12")]) - -(define_insn "*if_arith_arith" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (if_then_else:SI (match_operator 5 "comparison_operator" - [(match_operand 8 "cc_register" "") (const_int 0)]) - (match_operator:SI 6 "shiftable_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rI")]) - (match_operator:SI 7 "shiftable_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "arm_rhs_operand" "rI")])))] - "" - "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4" -[(set_attr "conds" "use") - (set_attr "length" "8")]) - -(define_insn "*ifcompare_arith_move" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (if_then_else:SI (match_operator 6 "comparison_operator" - [(match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_add_operand" "rIL,rIL")]) - (match_operator:SI 7 "shiftable_operator" - [(match_operand:SI 4 "s_register_operand" "r,r") - (match_operand:SI 5 "arm_rhs_operand" "rI,rI")]) - (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm"))) - (clobber (reg 24))] - "" - "* - /* If we have an operation where (op x 0) is the identity operation and - the conditional operator is LT or GE and we are comparing against zero and - everything is in registers then we can do this in two instructions */ - if (operands[3] == const0_rtx - && GET_CODE (operands[7]) != AND - && GET_CODE (operands[5]) == REG - && GET_CODE (operands[1]) == REG - && REGNO (operands[1]) == REGNO (operands[4]) - && REGNO (operands[4]) != REGNO (operands[0])) - { - if (GET_CODE (operands[6]) == LT) - return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; - else if (GET_CODE (operands[6]) == GE) - return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; - } - if (GET_CODE (operands[3]) == CONST_INT - && !const_ok_for_arm (INTVAL (operands[3]))) - output_asm_insn (\"cmn\\t%2, #%n3\", operands); - else - output_asm_insn (\"cmp\\t%2, %3\", operands); - output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands); - if (which_alternative != 0) - { - if (GET_CODE (operands[1]) == MEM) - return \"ldr%D6\\t%0, %1\"; - else - return \"mov%D6\\t%0, %1\"; - } - return \"\"; -" -[(set_attr "conds" "clob") - (set_attr "length" "8,12")]) - -(define_insn "*if_arith_move" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (if_then_else:SI (match_operator 4 "comparison_operator" - [(match_operand 6 "cc_register" "") (const_int 0)]) - (match_operator:SI 5 "shiftable_operator" - [(match_operand:SI 2 "s_register_operand" "r,r,r") - (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI")]) - (match_operand:SI 1 "arm_rhsm_operand" "0,?rI,m")))] - "" - "@ - %I5%d4\\t%0, %2, %3 - %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1 - %I5%d4\\t%0, %2, %3\;ldr%D4\\t%0, %1" -[(set_attr "conds" "use") - (set_attr "length" "4,8,8") - (set_attr "type" "*,*,load")]) - -(define_insn "*ifcompare_move_arith" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (if_then_else:SI (match_operator 6 "comparison_operator" - [(match_operand:SI 4 "s_register_operand" "r,r") - (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) - (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm") - (match_operator:SI 7 "shiftable_operator" - [(match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) - (clobber (reg 24))] - "" - "* - /* If we have an operation where (op x 0) is the identity operation and - the conditional operator is LT or GE and we are comparing against zero and - everything is in registers then we can do this in two instructions */ - if (operands[5] == const0_rtx - && GET_CODE (operands[7]) != AND - && GET_CODE (operands[3]) == REG - && GET_CODE (operands[1]) == REG - && REGNO (operands[1]) == REGNO (operands[2]) - && REGNO (operands[2]) != REGNO (operands[0])) - { - if (GET_CODE (operands[6]) == GE) - return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; - else if (GET_CODE (operands[6]) == LT) - return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; - } - - if (GET_CODE (operands[5]) == CONST_INT - && !const_ok_for_arm (INTVAL (operands[5]))) - output_asm_insn (\"cmn\\t%4, #%n5\", operands); - else - output_asm_insn (\"cmp\\t%4, %5\", operands); - - if (which_alternative != 0) - { - if (GET_CODE (operands[1]) == MEM) - output_asm_insn (\"ldr%d6\\t%0, %1\", operands); - else - output_asm_insn (\"mov%d6\\t%0, %1\", operands); - } - return \"%I7%D6\\t%0, %2, %3\"; -" -[(set_attr "conds" "clob") - (set_attr "length" "8,12")]) - -(define_insn "*if_move_arith" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (if_then_else:SI - (match_operator 4 "comparison_operator" - [(match_operand 6 "cc_register" "") (const_int 0)]) - (match_operand:SI 1 "arm_rhsm_operand" "0,?rI,m") - (match_operator:SI 5 "shiftable_operator" - [(match_operand:SI 2 "s_register_operand" "r,r,r") - (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI")])))] - "" - "@ - %I5%D4\\t%0, %2, %3 - %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1 - %I5%D4\\t%0, %2, %3\;ldr%d4\\t%0, %1" -[(set_attr "conds" "use") - (set_attr "length" "4,8,8") - (set_attr "type" "*,*,load")]) - -(define_insn "*ifcompare_move_not" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (if_then_else:SI - (match_operator 5 "comparison_operator" - [(match_operand:SI 3 "s_register_operand" "r,r") - (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) - (match_operand:SI 1 "arm_not_operand" "0,?rIK") - (not:SI - (match_operand:SI 2 "s_register_operand" "r,r")))) - (clobber (reg 24))] - "" - "#" -[(set_attr "conds" "clob") - (set_attr "length" "8,12")]) - -(define_insn "*if_move_not" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (if_then_else:SI - (match_operator 4 "comparison_operator" - [(match_operand 3 "cc_register" "") (const_int 0)]) - (match_operand:SI 1 "arm_not_operand" "0,?rI,K") - (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] - "" - "@ - mvn%D4\\t%0, %2 - mov%d4\\t%0, %1\;mvn%D4\\t%0, %2 - mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2" -[(set_attr "conds" "use") - (set_attr "length" "4,8,8")]) - -(define_insn "*ifcompare_not_move" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (if_then_else:SI - (match_operator 5 "comparison_operator" - [(match_operand:SI 3 "s_register_operand" "r,r") - (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) - (not:SI - (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) - (clobber (reg 24))] - "" - "#" -[(set_attr "conds" "clob") - (set_attr "length" "8,12")]) - -(define_insn "*if_not_move" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (if_then_else:SI - (match_operator 4 "comparison_operator" - [(match_operand 3 "cc_register" "") (const_int 0)]) - (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) - (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] - "" - "@ - mvn%d4\\t%0, %2 - mov%D4\\t%0, %1\;mvn%d4\\t%0, %2 - mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2" -[(set_attr "conds" "use") - (set_attr "length" "4,8,8")]) - -(define_insn "*ifcompare_shift_move" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (if_then_else:SI - (match_operator 6 "comparison_operator" - [(match_operand:SI 4 "s_register_operand" "r,r") - (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) - (match_operator:SI 7 "shift_operator" - [(match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]) - (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) - (clobber (reg 24))] - "" - "#" -[(set_attr "conds" "clob") - (set_attr "length" "8,12")]) - -(define_insn "*if_shift_move" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (if_then_else:SI - (match_operator 5 "comparison_operator" - [(match_operand 6 "cc_register" "") (const_int 0)]) - (match_operator:SI 4 "shift_operator" - [(match_operand:SI 2 "s_register_operand" "r,r,r") - (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")]) - (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] - "" - "@ - mov%d5\\t%0, %2%S4 - mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4 - mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4" -[(set_attr "conds" "use") - (set_attr "length" "4,8,8")]) - -(define_insn "*ifcompare_move_shift" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (if_then_else:SI - (match_operator 6 "comparison_operator" - [(match_operand:SI 4 "s_register_operand" "r,r") - (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) - (match_operand:SI 1 "arm_not_operand" "0,?rIK") - (match_operator:SI 7 "shift_operator" - [(match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]))) - (clobber (reg 24))] - "" - "#" -[(set_attr "conds" "clob") - (set_attr "length" "8,12")]) - -(define_insn "*if_move_shift" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (if_then_else:SI - (match_operator 5 "comparison_operator" - [(match_operand 6 "cc_register" "") (const_int 0)]) - (match_operand:SI 1 "arm_not_operand" "0,?rI,K") - (match_operator:SI 4 "shift_operator" - [(match_operand:SI 2 "s_register_operand" "r,r,r") - (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))] - "" - "@ - mov%D5\\t%0, %2%S4 - mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4 - mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4" -[(set_attr "conds" "use") - (set_attr "length" "4,8,8")]) - -(define_insn "*ifcompare_shift_shift" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (if_then_else:SI - (match_operator 7 "comparison_operator" - [(match_operand:SI 5 "s_register_operand" "r") - (match_operand:SI 6 "arm_add_operand" "rIL")]) - (match_operator:SI 8 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")]) - (match_operator:SI 9 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "arm_rhs_operand" "rM")]))) - (clobber (reg 24))] - "" - "#" -[(set_attr "conds" "clob") - (set_attr "length" "12")]) - -(define_insn "*if_shift_shift" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (if_then_else:SI - (match_operator 5 "comparison_operator" - [(match_operand 8 "cc_register" "") (const_int 0)]) - (match_operator:SI 6 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")]) - (match_operator:SI 7 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "arm_rhs_operand" "rM")])))] - "" - "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7" -[(set_attr "conds" "use") - (set_attr "length" "8")]) - -(define_insn "*ifcompare_not_arith" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (if_then_else:SI - (match_operator 6 "comparison_operator" - [(match_operand:SI 4 "s_register_operand" "r") - (match_operand:SI 5 "arm_add_operand" "rIL")]) - (not:SI (match_operand:SI 1 "s_register_operand" "r")) - (match_operator:SI 7 "shiftable_operator" - [(match_operand:SI 2 "s_register_operand" "r") - (match_operand:SI 3 "arm_rhs_operand" "rI")]))) - (clobber (reg 24))] - "" - "#" -[(set_attr "conds" "clob") - (set_attr "length" "12")]) - -(define_insn "*if_not_arith" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (if_then_else:SI - (match_operator 5 "comparison_operator" - [(match_operand 4 "cc_register" "") (const_int 0)]) - (not:SI (match_operand:SI 1 "s_register_operand" "r")) - (match_operator:SI 6 "shiftable_operator" - [(match_operand:SI 2 "s_register_operand" "r") - (match_operand:SI 3 "arm_rhs_operand" "rI")])))] - "" - "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3" -[(set_attr "conds" "use") - (set_attr "length" "8")]) - -(define_insn "*ifcompare_arith_not" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (if_then_else:SI - (match_operator 6 "comparison_operator" - [(match_operand:SI 4 "s_register_operand" "r") - (match_operand:SI 5 "arm_add_operand" "rIL")]) - (match_operator:SI 7 "shiftable_operator" - [(match_operand:SI 2 "s_register_operand" "r") - (match_operand:SI 3 "arm_rhs_operand" "rI")]) - (not:SI (match_operand:SI 1 "s_register_operand" "r")))) - (clobber (reg 24))] - "" - "#" -[(set_attr "conds" "clob") - (set_attr "length" "12")]) - -(define_insn "*if_arith_not" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (if_then_else:SI - (match_operator 5 "comparison_operator" - [(match_operand 4 "cc_register" "") (const_int 0)]) - (match_operator:SI 6 "shiftable_operator" - [(match_operand:SI 2 "s_register_operand" "r") - (match_operand:SI 3 "arm_rhs_operand" "rI")]) - (not:SI (match_operand:SI 1 "s_register_operand" "r"))))] - "" - "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3" -[(set_attr "conds" "use") - (set_attr "length" "8")]) - -(define_insn "*ifcompare_neg_move" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (if_then_else:SI - (match_operator 5 "comparison_operator" - [(match_operand:SI 3 "s_register_operand" "r,r") - (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) - (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) - (clobber (reg:CC 24))] - "" - "#" -[(set_attr "conds" "clob") - (set_attr "length" "8,12")]) - -(define_insn "*if_neg_move" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (if_then_else:SI - (match_operator 4 "comparison_operator" - [(match_operand 3 "cc_register" "") (const_int 0)]) - (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) - (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] - "" - "@ - rsb%d4\\t%0, %2, #0 - mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0 - mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0" -[(set_attr "conds" "use") - (set_attr "length" "4,8,8")]) - -(define_insn "*ifcompare_move_neg" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (if_then_else:SI - (match_operator 5 "comparison_operator" - [(match_operand:SI 3 "s_register_operand" "r,r") - (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) - (match_operand:SI 1 "arm_not_operand" "0,?rIK") - (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")))) - (clobber (reg:CC 24))] - "" - "#" -[(set_attr "conds" "clob") - (set_attr "length" "8,12")]) - -(define_insn "*if_move_neg" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (if_then_else:SI - (match_operator 4 "comparison_operator" - [(match_operand 3 "cc_register" "") (const_int 0)]) - (match_operand:SI 1 "arm_not_operand" "0,?rI,K") - (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] - "" - "@ - rsb%D4\\t%0, %2, #0 - mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0 - mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0" -[(set_attr "conds" "use") - (set_attr "length" "4,8,8")]) - -(define_insn "*arith_adjacentmem" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (match_operator:SI 1 "shiftable_operator" - [(match_operand:SI 2 "memory_operand" "m") - (match_operand:SI 3 "memory_operand" "m")])) - (clobber (match_scratch:SI 4 "=r"))] - "adjacent_mem_locations (operands[2], operands[3])" - "* -{ - rtx ldm[3]; - rtx arith[4]; - int val1 = 0, val2 = 0; - - if (REGNO (operands[0]) > REGNO (operands[4])) - { - ldm[1] = operands[4]; - ldm[2] = operands[0]; - } - else - { - ldm[1] = operands[0]; - ldm[2] = operands[4]; - } - if (GET_CODE (XEXP (operands[2], 0)) != REG) - val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1)); - if (GET_CODE (XEXP (operands[3], 0)) != REG) - val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1)); - arith[0] = operands[0]; - arith[3] = operands[1]; - if (val1 < val2) - { - arith[1] = ldm[1]; - arith[2] = ldm[2]; - } - else - { - arith[1] = ldm[2]; - arith[2] = ldm[1]; - } - if (val1 && val2) - { - rtx ops[3]; - ldm[0] = ops[0] = operands[4]; - ops[1] = XEXP (XEXP (operands[2], 0), 0); - ops[2] = XEXP (XEXP (operands[2], 0), 1); - output_add_immediate (ops); - if (val1 < val2) - output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); - else - output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); - } - else if (val1) - { - ldm[0] = XEXP (operands[3], 0); - if (val1 < val2) - output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); - else - output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); - } - else - { - ldm[0] = XEXP (operands[2], 0); - if (val1 < val2) - output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); - else - output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); - } - output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith); - return \"\"; -} -" -[(set_attr "length" "12") - (set_attr "type" "load")]) - -;; the arm can support extended pre-inc instructions - -;; In all these cases, we use operands 0 and 1 for the register being -;; incremented because those are the operands that local-alloc will -;; tie and these are the pair most likely to be tieable (and the ones -;; that will benefit the most). - -;; We reject the frame pointer if it occurs anywhere in these patterns since -;; elimination will cause too many headaches. - -(define_insn "*strqi_preinc" - [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") - (match_operand:SI 2 "index_operand" "rJ"))) - (match_operand:QI 3 "s_register_operand" "r")) - (set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (match_dup 1) (match_dup 2)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" - "str%?b\\t%3, [%0, %2]!" -[(set_attr "type" "store1")]) - -(define_insn "*strqi_predec" - [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") - (match_operand:SI 2 "s_register_operand" "r"))) - (match_operand:QI 3 "s_register_operand" "r")) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_dup 2)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" - "str%?b\\t%3, [%0, -%2]!" -[(set_attr "type" "store1")]) - -(define_insn "*loadqi_preinc" - [(set (match_operand:QI 3 "s_register_operand" "=r") - (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") - (match_operand:SI 2 "index_operand" "rJ")))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (match_dup 1) (match_dup 2)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" - "ldr%?b\\t%3, [%0, %2]!" -[(set_attr "type" "load")]) - -(define_insn "*loadqi_predec" - [(set (match_operand:QI 3 "s_register_operand" "=r") - (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") - (match_operand:SI 2 "s_register_operand" "r")))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_dup 2)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" - "ldr%?b\\t%3, [%0, -%2]!" -[(set_attr "type" "load")]) - -(define_insn "*loadqisi_preinc" - [(set (match_operand:SI 3 "s_register_operand" "=r") - (zero_extend:SI - (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") - (match_operand:SI 2 "index_operand" "rJ"))))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (match_dup 1) (match_dup 2)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" - "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi" -[(set_attr "type" "load")]) - -(define_insn "*loadqisi_predec" - [(set (match_operand:SI 3 "s_register_operand" "=r") - (zero_extend:SI - (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") - (match_operand:SI 2 "s_register_operand" "r"))))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_dup 2)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" - "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi" -[(set_attr "type" "load")]) - -(define_insn "*strsi_preinc" - [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") - (match_operand:SI 2 "index_operand" "rJ"))) - (match_operand:SI 3 "s_register_operand" "r")) - (set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (match_dup 1) (match_dup 2)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" - "str%?\\t%3, [%0, %2]!" -[(set_attr "type" "store1")]) - -(define_insn "*strqi_predec" - [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") - (match_operand:SI 2 "s_register_operand" "r"))) - (match_operand:SI 3 "s_register_operand" "r")) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_dup 2)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" - "str%?\\t%3, [%0, -%2]!" -[(set_attr "type" "store1")]) - -(define_insn "*loadsi_preinc" - [(set (match_operand:SI 3 "s_register_operand" "=r") - (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") - (match_operand:SI 2 "index_operand" "rJ")))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (match_dup 1) (match_dup 2)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" - "ldr%?\\t%3, [%0, %2]!" -[(set_attr "type" "load")]) - -(define_insn "*loadsi_predec" - [(set (match_operand:SI 3 "s_register_operand" "=r") - (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") - (match_operand:SI 2 "s_register_operand" "r")))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_dup 2)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" - "ldr%?\\t%3, [%0, -%2]!" -[(set_attr "type" "load")]) - -(define_insn "*loadhi_preinc" - [(set (match_operand:HI 3 "s_register_operand" "=r") - (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") - (match_operand:SI 2 "index_operand" "rJ")))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (match_dup 1) (match_dup 2)))] - "(! BYTES_BIG_ENDIAN) - && ! TARGET_SHORT_BY_BYTES - && REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" - "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi" -[(set_attr "type" "load")]) - -(define_insn "*loadhi_predec" - [(set (match_operand:HI 3 "s_register_operand" "=r") - (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") - (match_operand:SI 2 "s_register_operand" "r")))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_dup 2)))] - "(!BYTES_BIG_ENDIAN) - && ! TARGET_SHORT_BY_BYTES - && REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" - "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi" -[(set_attr "type" "load")]) - -(define_insn "*strqi_shiftpreinc" - [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_shift_operand" "n")]) - (match_operand:SI 1 "s_register_operand" "0"))) - (match_operand:QI 5 "s_register_operand" "r")) - (set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) - (match_dup 1)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && REGNO (operands[3]) != FRAME_POINTER_REGNUM" - "str%?b\\t%5, [%0, %3%S2]!" -[(set_attr "type" "store1")]) - -(define_insn "*strqi_shiftpredec" - [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_shift_operand" "n")]))) - (match_operand:QI 5 "s_register_operand" "r")) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) - (match_dup 4)])))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && REGNO (operands[3]) != FRAME_POINTER_REGNUM" - "str%?b\\t%5, [%0, -%3%S2]!" -[(set_attr "type" "store1")]) - -(define_insn "*loadqi_shiftpreinc" - [(set (match_operand:QI 5 "s_register_operand" "=r") - (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_shift_operand" "n")]) - (match_operand:SI 1 "s_register_operand" "0")))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) - (match_dup 1)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && REGNO (operands[3]) != FRAME_POINTER_REGNUM" - "ldr%?b\\t%5, [%0, %3%S2]!" -[(set_attr "type" "load")]) - -(define_insn "*loadqi_shiftpredec" - [(set (match_operand:QI 5 "s_register_operand" "=r") - (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_shift_operand" "n")])))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) - (match_dup 4)])))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && REGNO (operands[3]) != FRAME_POINTER_REGNUM" - "ldr%?b\\t%5, [%0, -%3%S2]!" -[(set_attr "type" "load")]) - -(define_insn "*strsi_shiftpreinc" - [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_shift_operand" "n")]) - (match_operand:SI 1 "s_register_operand" "0"))) - (match_operand:SI 5 "s_register_operand" "r")) - (set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) - (match_dup 1)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && REGNO (operands[3]) != FRAME_POINTER_REGNUM" - "str%?\\t%5, [%0, %3%S2]!" -[(set_attr "type" "store1")]) - -(define_insn "*strsi_shiftpredec" - [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_shift_operand" "n")]))) - (match_operand:SI 5 "s_register_operand" "r")) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) - (match_dup 4)])))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && REGNO (operands[3]) != FRAME_POINTER_REGNUM" - "str%?\\t%5, [%0, -%3%S2]!" -[(set_attr "type" "store1")]) - -(define_insn "*loadqi_shiftpreinc" - [(set (match_operand:SI 5 "s_register_operand" "=r") - (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_shift_operand" "n")]) - (match_operand:SI 1 "s_register_operand" "0")))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) - (match_dup 1)))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && REGNO (operands[3]) != FRAME_POINTER_REGNUM" - "ldr%?\\t%5, [%0, %3%S2]!" -[(set_attr "type" "load")]) - -(define_insn "*loadqi_shiftpredec" - [(set (match_operand:SI 5 "s_register_operand" "=r") - (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_shift_operand" "n")])))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) - (match_dup 4)])))] - "REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && REGNO (operands[3]) != FRAME_POINTER_REGNUM" - "ldr%?\\t%5, [%0, -%3%S2]!" -[(set_attr "type" "load")]) - -(define_insn "*loadhi_shiftpreinc" - [(set (match_operand:HI 5 "s_register_operand" "=r") - (mem:HI (plus:SI (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_shift_operand" "n")]) - (match_operand:SI 1 "s_register_operand" "0")))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) - (match_dup 1)))] - "(! BYTES_BIG_ENDIAN) - && ! TARGET_SHORT_BY_BYTES - && REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && REGNO (operands[3]) != FRAME_POINTER_REGNUM" - "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi" -[(set_attr "type" "load")]) - -(define_insn "*loadhi_shiftpredec" - [(set (match_operand:HI 5 "s_register_operand" "=r") - (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_shift_operand" "n")])))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) - (match_dup 4)])))] - "(! BYTES_BIG_ENDIAN) - && ! TARGET_SHORT_BY_BYTES - && REGNO (operands[0]) != FRAME_POINTER_REGNUM - && REGNO (operands[1]) != FRAME_POINTER_REGNUM - && REGNO (operands[3]) != FRAME_POINTER_REGNUM" - "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi" -[(set_attr "type" "load")]) - -; It can also support extended post-inc expressions, but combine doesn't -; try these.... -; It doesn't seem worth adding peepholes for anything but the most common -; cases since, unlike combine, the increment must immediately follow the load -; for this pattern to match. -; When loading we must watch to see that the base register isn't trampled by -; the load. In such cases this isn't a post-inc expression. - -(define_peephole - [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r")) - (match_operand:QI 2 "s_register_operand" "r")) - (set (match_dup 0) - (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] - "" - "str%?b\\t%2, [%0], %1") - -(define_peephole - [(set (match_operand:QI 0 "s_register_operand" "=r") - (mem:QI (match_operand:SI 1 "s_register_operand" "+r"))) - (set (match_dup 1) - (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] - "REGNO(operands[0]) != REGNO(operands[1]) - && (GET_CODE (operands[2]) != REG - || REGNO(operands[0]) != REGNO (operands[2]))" - "ldr%?b\\t%0, [%1], %2") - -(define_peephole - [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r")) - (match_operand:SI 2 "s_register_operand" "r")) - (set (match_dup 0) - (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] - "" - "str%?\\t%2, [%0], %1") - -(define_peephole - [(set (match_operand:HI 0 "s_register_operand" "=r") - (mem:HI (match_operand:SI 1 "s_register_operand" "+r"))) - (set (match_dup 1) - (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] - "(! BYTES_BIG_ENDIAN) - && ! TARGET_SHORT_BY_BYTES - && REGNO(operands[0]) != REGNO(operands[1]) - && (GET_CODE (operands[2]) != REG - || REGNO(operands[0]) != REGNO (operands[2]))" - "ldr%?\\t%0, [%1], %2\\t%@ loadhi") - -(define_peephole - [(set (match_operand:SI 0 "s_register_operand" "=r") - (mem:SI (match_operand:SI 1 "s_register_operand" "+r"))) - (set (match_dup 1) - (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] - "REGNO(operands[0]) != REGNO(operands[1]) - && (GET_CODE (operands[2]) != REG - || REGNO(operands[0]) != REGNO (operands[2]))" - "ldr%?\\t%0, [%1], %2") - -(define_peephole - [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r") - (match_operand:SI 1 "index_operand" "rJ"))) - (match_operand:QI 2 "s_register_operand" "r")) - (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] - "" - "str%?b\\t%2, [%0, %1]!") - -(define_peephole - [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator" - [(match_operand:SI 0 "s_register_operand" "r") - (match_operand:SI 1 "const_int_operand" "n")]) - (match_operand:SI 2 "s_register_operand" "+r"))) - (match_operand:QI 3 "s_register_operand" "r")) - (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)]) - (match_dup 2)))] - "" - "str%?b\\t%3, [%2, %0%S4]!") - -; This pattern is never tried by combine, so do it as a peephole - -(define_peephole - [(set (match_operand:SI 0 "s_register_operand" "=r") - (match_operand:SI 1 "s_register_operand" "r")) - (set (reg:CC 24) - (compare:CC (match_dup 1) (const_int 0)))] - "" - "sub%?s\\t%0, %1, #0" -[(set_attr "conds" "set")]) - -; Peepholes to spot possible load- and store-multiples, if the ordering is -; reversed, check that the memory references aren't volatile. - -(define_peephole - [(set (match_operand:SI 0 "s_register_operand" "=r") - (match_operand:SI 4 "memory_operand" "m")) - (set (match_operand:SI 1 "s_register_operand" "=r") - (match_operand:SI 5 "memory_operand" "m")) - (set (match_operand:SI 2 "s_register_operand" "=r") - (match_operand:SI 6 "memory_operand" "m")) - (set (match_operand:SI 3 "s_register_operand" "=r") - (match_operand:SI 7 "memory_operand" "m"))] - "load_multiple_sequence (operands, 4, NULL, NULL, NULL)" - "* - return emit_ldm_seq (operands, 4); -") - -(define_peephole - [(set (match_operand:SI 0 "s_register_operand" "=r") - (match_operand:SI 3 "memory_operand" "m")) - (set (match_operand:SI 1 "s_register_operand" "=r") - (match_operand:SI 4 "memory_operand" "m")) - (set (match_operand:SI 2 "s_register_operand" "=r") - (match_operand:SI 5 "memory_operand" "m"))] - "load_multiple_sequence (operands, 3, NULL, NULL, NULL)" - "* - return emit_ldm_seq (operands, 3); -") - -(define_peephole - [(set (match_operand:SI 0 "s_register_operand" "=r") - (match_operand:SI 2 "memory_operand" "m")) - (set (match_operand:SI 1 "s_register_operand" "=r") - (match_operand:SI 3 "memory_operand" "m"))] - "load_multiple_sequence (operands, 2, NULL, NULL, NULL)" - "* - return emit_ldm_seq (operands, 2); -") - -(define_peephole - [(set (match_operand:SI 4 "memory_operand" "=m") - (match_operand:SI 0 "s_register_operand" "r")) - (set (match_operand:SI 5 "memory_operand" "=m") - (match_operand:SI 1 "s_register_operand" "r")) - (set (match_operand:SI 6 "memory_operand" "=m") - (match_operand:SI 2 "s_register_operand" "r")) - (set (match_operand:SI 7 "memory_operand" "=m") - (match_operand:SI 3 "s_register_operand" "r"))] - "store_multiple_sequence (operands, 4, NULL, NULL, NULL)" - "* - return emit_stm_seq (operands, 4); -") - -(define_peephole - [(set (match_operand:SI 3 "memory_operand" "=m") - (match_operand:SI 0 "s_register_operand" "r")) - (set (match_operand:SI 4 "memory_operand" "=m") - (match_operand:SI 1 "s_register_operand" "r")) - (set (match_operand:SI 5 "memory_operand" "=m") - (match_operand:SI 2 "s_register_operand" "r"))] - "store_multiple_sequence (operands, 3, NULL, NULL, NULL)" - "* - return emit_stm_seq (operands, 3); -") - -(define_peephole - [(set (match_operand:SI 2 "memory_operand" "=m") - (match_operand:SI 0 "s_register_operand" "r")) - (set (match_operand:SI 3 "memory_operand" "=m") - (match_operand:SI 1 "s_register_operand" "r"))] - "store_multiple_sequence (operands, 2, NULL, NULL, NULL)" - "* - return emit_stm_seq (operands, 2); -") - -;; A call followed by return can be replaced by restoring the regs and -;; jumping to the subroutine, provided we aren't passing the address of -;; any of our local variables. If we call alloca then this is unsafe -;; since restoring the frame frees the memory, which is not what we want. -;; Sometimes the return might have been targeted by the final prescan: -;; if so then emit a proper return insn as well. -;; Unfortunately, if the frame pointer is required, we don't know if the -;; current function has any implicit stack pointer adjustments that will -;; be restored by the return: we can't therefore do a tail call. -;; Another unfortunate that we can't handle is if current_function_args_size -;; is non-zero: in this case elimination of the argument pointer assumed -;; that lr was pushed onto the stack, so eliminating upsets the offset -;; calculations. - -(define_peephole - [(parallel [(call (mem:SI (match_operand:SI 0 "" "X")) - (match_operand:SI 1 "general_operand" "g")) - (clobber (reg:SI 14))]) - (return)] - "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN - && !get_frame_size () && !current_function_calls_alloca - && !frame_pointer_needed && !current_function_args_size)" - "* -{ - extern rtx arm_target_insn; - extern int arm_ccfsm_state; - - if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn)) - { - arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc); - output_return_instruction (NULL, TRUE, FALSE); - arm_ccfsm_state = 0; - arm_target_insn = NULL; - } - - output_return_instruction (NULL, FALSE, FALSE); - return \"b%?\\t%a0\"; -}" -[(set_attr "type" "call") - (set_attr "length" "8")]) - -(define_peephole - [(parallel [(set (match_operand 0 "s_register_operand" "=rf") - (call (mem:SI (match_operand:SI 1 "" "X")) - (match_operand:SI 2 "general_operand" "g"))) - (clobber (reg:SI 14))]) - (return)] - "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN - && !get_frame_size () && !current_function_calls_alloca - && !frame_pointer_needed && !current_function_args_size)" - "* -{ - extern rtx arm_target_insn; - extern int arm_ccfsm_state; - - if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn)) - { - arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc); - output_return_instruction (NULL, TRUE, FALSE); - arm_ccfsm_state = 0; - arm_target_insn = NULL; - } - - output_return_instruction (NULL, FALSE, FALSE); - return \"b%?\\t%a1\"; -}" -[(set_attr "type" "call") - (set_attr "length" "8")]) - -;; As above but when this function is not void, we must be returning the -;; result of the called subroutine. - -(define_peephole - [(parallel [(set (match_operand 0 "s_register_operand" "=rf") - (call (mem:SI (match_operand:SI 1 "" "X")) - (match_operand:SI 2 "general_operand" "g"))) - (clobber (reg:SI 14))]) - (use (match_dup 0)) - (return)] - "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN - && !get_frame_size () && !current_function_calls_alloca - && !frame_pointer_needed && !current_function_args_size)" - "* -{ - extern rtx arm_target_insn; - extern int arm_ccfsm_state; - - if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn)) - { - arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc); - output_return_instruction (NULL, TRUE, FALSE); - arm_ccfsm_state = 0; - arm_target_insn = NULL; - } - - output_return_instruction (NULL, FALSE, FALSE); - return \"b%?\\t%a1\"; -}" -[(set_attr "type" "call") - (set_attr "length" "8")]) - -;; If calling a subroutine and then jumping back to somewhere else, but not -;; too far away, then we can set the link register with the branch address -;; and jump direct to the subroutine. On return from the subroutine -;; execution continues at the branch; this avoids a prefetch stall. -;; We use the length attribute (via short_branch ()) to establish whether or -;; not this is possible, this is the same as the sparc does. - -(define_peephole - [(parallel[(call (mem:SI (match_operand:SI 0 "" "X")) - (match_operand:SI 1 "general_operand" "g")) - (clobber (reg:SI 14))]) - (set (pc) - (label_ref (match_operand 2 "" "")))] - "0 && GET_CODE (operands[0]) == SYMBOL_REF - && short_branch (INSN_UID (insn), INSN_UID (operands[2])) - && arm_insn_not_targeted (insn)" - "* -{ - int backward = arm_backwards_branch (INSN_UID (insn), - INSN_UID (operands[2])); - -#if 0 - /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or - * above, leaving it out means that the code will still run on an arm 2 or 3 - */ - if (TARGET_6) - { - if (backward) - output_asm_insn (\"sub%?\\t%|lr, %|pc, #(8 + . -%l2)\", operands); - else - output_asm_insn (\"add%?\\t%|lr, %|pc, #(%l2 - . -8)\", operands); - } - else -#endif - { - output_asm_insn (\"mov%?\\t%|lr, %|pc\\t%@ protect cc\", operands); - if (backward) - output_asm_insn (\"sub%?\\t%|lr, %|lr, #(4 + . -%l2)\", operands); - else - output_asm_insn (\"add%?\\t%|lr, %|lr, #(%l2 - . -4)\", operands); - } - return \"b%?\\t%a0\"; -}" -[(set_attr "type" "call") - (set (attr "length") - (if_then_else (eq_attr "prog_mode" "prog32") - (const_int 8) - (const_int 12)))]) - -(define_peephole - [(parallel[(set (match_operand:SI 0 "s_register_operand" "=r") - (call (mem:SI (match_operand:SI 1 "" "X")) - (match_operand:SI 2 "general_operand" "g"))) - (clobber (reg:SI 14))]) - (set (pc) - (label_ref (match_operand 3 "" "")))] - "0 && GET_CODE (operands[0]) == SYMBOL_REF - && short_branch (INSN_UID (insn), INSN_UID (operands[3])) - && arm_insn_not_targeted (insn)" - "* -{ - int backward = arm_backwards_branch (INSN_UID (insn), - INSN_UID (operands[3])); - -#if 0 - /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or - * above, leaving it out means that the code will still run on an arm 2 or 3 - */ - if (TARGET_6) - { - if (backward) - output_asm_insn (\"sub%?\\t%|lr, %|pc, #(8 + . -%l3)\", operands); - else - output_asm_insn (\"add%?\\t%|lr, %|pc, #(%l3 - . -8)\", operands); - } - else -#endif - { - output_asm_insn (\"mov%?\\t%|lr, %|pc\\t%@ protect cc\", operands); - if (backward) - output_asm_insn (\"sub%?\\t%|lr, %|lr, #(4 + . -%l3)\", operands); - else - output_asm_insn (\"add%?\\t%|lr, %|lr, #(%l3 - . -4)\", operands); - } - return \"b%?\\t%a1\"; -}" -[(set_attr "type" "call") - (set (attr "length") - (if_then_else (eq_attr "prog_mode" "prog32") - (const_int 8) - (const_int 12)))]) - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "") - (const_int 0)) - (neg:SI (match_operator:SI 2 "comparison_operator" - [(match_operand:SI 3 "s_register_operand" "") - (match_operand:SI 4 "arm_rhs_operand" "")])))) - (clobber (match_operand:SI 5 "s_register_operand" ""))] - "" - [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31)))) - (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) - (match_dup 5)))] - "") - -;; This split can be used because CC_Z mode implies that the following -;; branch will be an equality, or an unsigned inequality, so the sign -;; extension is not needed. - -(define_split - [(set (reg:CC_Z 24) - (compare:CC_Z - (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0) - (const_int 24)) - (match_operand 1 "const_int_operand" ""))) - (clobber (match_scratch:SI 2 ""))] - "((unsigned HOST_WIDE_INT) INTVAL (operands[1])) - == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24" - [(set (match_dup 2) (zero_extend:SI (match_dup 0))) - (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))] - " - operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24); -") - -(define_expand "prologue" - [(clobber (const_int 0))] - "" - " - arm_expand_prologue (); - DONE; -") - -;; This split is only used during output to reduce the number of patterns -;; that need assembler instructions adding to them. We allowed the setting -;; of the conditions to be implicit during rtl generation so that -;; the conditional compare patterns would work. However this conflicts to -;; some extent with the conditional data operations, so we have to split them -;; up again here. - -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (if_then_else:SI (match_operator 1 "comparison_operator" - [(match_operand 2 "" "") (match_operand 3 "" "")]) - (match_operand 4 "" "") - (match_operand 5 "" ""))) - (clobber (reg 24))] - "reload_completed" - [(set (match_dup 6) (match_dup 7)) - (set (match_dup 0) - (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)]) - (match_dup 4) - (match_dup 5)))] - " -{ - enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2], - operands[3]); - - operands[6] = gen_rtx (REG, mode, 24); - operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]); -} -") - - -;; The next two patterns occur when an AND operation is followed by a -;; scc insn sequence - -(define_insn "*sign_extract_onebit" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") - (const_int 1) - (match_operand:SI 2 "const_int_operand" "n")))] - "" - "* - operands[2] = GEN_INT (1 << INTVAL (operands[2])); - output_asm_insn (\"ands\\t%0, %1, %2\", operands); - return \"mvnne\\t%0, #0\"; -" -[(set_attr "conds" "clob") - (set_attr "length" "8")]) - -(define_insn "*not_signextract_onebit" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (not:SI - (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") - (const_int 1) - (match_operand:SI 2 "const_int_operand" "n"))))] - "" - "* - operands[2] = GEN_INT (1 << INTVAL (operands[2])); - output_asm_insn (\"tst\\t%1, %2\", operands); - output_asm_insn (\"mvneq\\t%0, #0\", operands); - return \"movne\\t%0, #0\"; -" -[(set_attr "conds" "clob") - (set_attr "length" "12")]) - -;; Push multiple registers to the stack. The first register is in the -;; unspec part of the insn; subsequent registers are in parallel (use ...) -;; expressions. -(define_insn "*push_multi" - [(match_parallel 2 "multi_register_push" - [(set (match_operand:BLK 0 "memory_operand" "=m") - (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])] - "" - "* -{ - char pattern[100]; - int i; - extern int lr_save_eliminated; - - if (lr_save_eliminated) - { - if (XVECLEN (operands[2], 0) > 1) - abort (); - return \"\"; - } - strcpy (pattern, \"stmfd\\t%m0!, {%1\"); - for (i = 1; i < XVECLEN (operands[2], 0); i++) - { - strcat (pattern, \", %|\"); - strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), - 0))]); - } - strcat (pattern, \"}\"); - output_asm_insn (pattern, operands); - return \"\"; -}" -[(set_attr "type" "store4")]) - -;; Special patterns for dealing with the constant pool - -(define_insn "consttable_4" - [(unspec_volatile [(match_operand 0 "" "")] 2)] - "" - "* -{ - switch (GET_MODE_CLASS (GET_MODE (operands[0]))) - { - case MODE_FLOAT: - { - union real_extract u; - bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u); - assemble_real (u.d, GET_MODE (operands[0])); - break; - } - default: - assemble_integer (operands[0], 4, 1); - break; - } - return \"\"; -}" -[(set_attr "length" "4")]) - -(define_insn "consttable_8" - [(unspec_volatile [(match_operand 0 "" "")] 3)] - "" - "* -{ - switch (GET_MODE_CLASS (GET_MODE (operands[0]))) - { - case MODE_FLOAT: - { - union real_extract u; - bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u); - assemble_real (u.d, GET_MODE (operands[0])); - break; - } - default: - assemble_integer (operands[0], 8, 1); - break; - } - return \"\"; -}" -[(set_attr "length" "8")]) - -(define_insn "consttable_end" - [(unspec_volatile [(const_int 0)] 4)] - "" - "* - /* Nothing to do (currently). */ - return \"\"; -") - -(define_insn "align_4" - [(unspec_volatile [(const_int 0)] 5)] - "" - "* - assemble_align (32); - return \"\"; -") |