URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [epiphany/] [epiphany.md] - Rev 709
Compare with Previous | Blame | View Log
;; Machine description of the Adaptiva epiphany cpu for GNU C compiler;; Copyright (C) 1994, 1997, 1998, 1999, 2000, 2004, 2005, 2007, 2009, 2010,;; 2011 Free Software Foundation, Inc.;; Contributed by Embecosm on behalf of Adapteva, Inc.;; This file is part of GCC.;; GCC 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 3, or (at your option);; any later version.;; GCC 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 GCC; see the file COPYING3. If not see;; <http://www.gnu.org/licenses/>.;; See file "rtl.def" for documentation on define_insn, match_*, et. al.(define_constants[(GPR_0 0)(GPR_FP 11)(GPR_IP 12)(GPR_SP 13)(GPR_LR 14)(GPR_16 16)(GPR_18 18)(GPR_20 20)(ARG_POINTER_REGNUM 64)(FRAME_POINTER_REGNUM 65)(CC_REGNUM 66) ;; 66 or 17(CCFP_REGNUM 67) ;; 67 or 18(CONFIG_REGNUM 68)(STATUS_REGNUM 69)(LC_REGNUM 70)(LS_REGNUM 71)(LE_REGNUM 72)(IRET_REGNUM 73)(FP_NEAREST_REGNUM 74)(FP_TRUNCATE_REGNUM 75)(FP_ANYFP_REGNUM 76)(UNKNOWN_REGNUM 77) ; used for addsi3_r and friends; We represent the return address as an unspec rather than a reg.; If we used a reg, we could use register elimination, but eliminating; to GPR_LR would make the latter visible to dataflow, thus making it; harder to determine when it must be saved.(UNSPEC_RETURN_ADDR 0)(UNSPEC_FP_MODE 1)(UNSPECV_GID 0)(UNSPECV_GIE 1)]);; Insn type. Used to default other attribute values.(define_attr "type""move,load,store,cmove,unary,compare,shift,mul,uncond_branch,branch,call,fp,fp_int,misc,sfunc,fp_sfunc,flow"(const_string "misc"));; Length (in # bytes)(define_attr "length" "" (const_int 4));; The length here is the length of a single asm.(define_asm_attributes[(set_attr "length" "4")(set_attr "type" "misc")]);; pipeline model; so far we have only one.(define_attr "pipe_model" "epiphany" (const_string "epiphany"))(define_attr "rounding" "trunc,nearest"(cond [(ne (symbol_ref "TARGET_ROUND_NEAREST") (const_int 0))(const_string "nearest")](const_string "trunc")))(define_attr "fp_mode" "round_unknown,round_nearest,round_trunc,int,caller,none"(cond [(eq_attr "type" "fp,fp_sfunc")(symbol_ref "(enum attr_fp_mode) epiphany_normal_fp_rounding")(eq_attr "type" "call")(symbol_ref "(enum attr_fp_mode) epiphany_normal_fp_mode")(eq_attr "type" "fp_int")(const_string "int")](const_string "none")))(include "epiphany-sched.md")(include "predicates.md")(include "constraints.md");; modes that are held in a single register, and hence, a word.(define_mode_iterator WMODE [SI SF HI QI V2HI V4QI])(define_mode_iterator WMODE2 [SI SF HI QI V2HI V4QI]);; modes that are held in a two single registers(define_mode_iterator DWMODE [DI DF V2SI V2SF V4HI V8QI]);; Double-word mode made up of two single-word mode values.(define_mode_iterator DWV2MODE [V2SI V2SF])(define_mode_attr vmode_part [(V2SI "si") (V2SF "sf")])(define_mode_attr vmode_PART [(V2SI "SI") (V2SF "SF")])(define_mode_attr vmode_fp_type [(V2SI "fp_int") (V2SF "fp")])(define_mode_attr vmode_ccmode [(V2SI "CC") (V2SF "CC_FP")])(define_mode_attr vmode_cc [(V2SI "CC_REGNUM") (V2SF "CCFP_REGNUM")]);; Move instructions.(define_expand "mov<mode>"[(set (match_operand:WMODE 0 "general_operand" "")(match_operand:WMODE 1 "general_operand" ""))]""{if (<MODE>mode == V4QImode || <MODE>mode == V2HImode){operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);operands[1] = simplify_gen_subreg (SImode, operands[1], <MODE>mode, 0);emit_insn (gen_movsi (operands[0], operands[1]));DONE;}if (GET_CODE (operands[0]) == MEM)operands[1] = force_reg (<MODE>mode, operands[1]);if (<MODE>mode == SImode&& (operands[1] == frame_pointer_rtx || operands[1] == arg_pointer_rtx)){rtx reg = operands[0];if (!REG_P (reg))reg = gen_reg_rtx (SImode);emit_insn (gen_move_frame (reg, operands[1]));operands[1] = reg;if (operands[0] == reg)DONE;}})(define_insn "*movqi_insn"[(set (match_operand:QI 0 "move_dest_operand" "=Rcs, r, r,r,m")(match_operand:QI 1 "move_src_operand" "Rcs,rU16,Cal,m,r"))];; ??? Needed?"gpr_operand (operands[0], QImode)|| gpr_operand (operands[1], QImode)""@mov %0,%1mov %0,%1mov %0,%1ldrb %0,%1strb %1,%0"[(set_attr "type" "move,move,move,load,store")])(define_insn_and_split "*movhi_insn"[(set (match_operand:HI 0 "move_dest_operand" "=r, r,r,m")(match_operand:HI 1 "move_src_operand""rU16,Cal,m,r"))]"gpr_operand (operands[0], HImode)|| gpr_operand (operands[1], HImode)""@mov %0,%1mov %0,%%low(%1); %1ldrh %0,%c1strh %1,%c0""reload_completed && CONSTANT_P (operands[1])&& !satisfies_constraint_U16 (operands[1]) && TARGET_SPLIT_LOHI"[(set (match_dup 2) (match_dup 3))]"operands[2] = simplify_gen_subreg (SImode, operands[0], HImode, 0);operands[3] = simplify_gen_subreg (SImode, operands[1], HImode, 0);"[(set_attr "type" "move,move,load,store")]);; We use a special pattern for a move from the frame pointer to;; show the flag clobber that is needed when this move is changed;; to an add by register elimination.;; ??? A pseudo register might be equivalent to a function invariant,;; and thus placed by reload into reg_equiv_invariant; if the pseudo;; does not get a hard register, we then end up with the function;; invariant in its place, i.e. an unexpected clobber of the flags;; register.;;;; N.B. operand 1 is an operand so that reload will perform elimination.;;;; The post-reload pattern recognition and splitting is done in frame_move_1.(define_insn "move_frame"[(set (match_operand:SI 0 "gpr_operand" "=r")(match_operand:SI 1 "register_operand" "r"))(clobber (reg:CC CC_REGNUM))]"operands[1] == frame_pointer_rtx || operands[1] == arg_pointer_rtx""#")(define_insn "movsi_high"[(set (match_operand:SI 0 "gpr_operand" "+r")(ior:SI (and:SI (match_dup 0) (const_int 65535))(high:SI (match_operand:SI 1 "move_src_operand" "i"))))]"""movt %0, %%high(%1)"[(set_attr "type" "move")(set_attr "length" "4")])(define_insn "movsi_lo_sum"[(set (match_operand:SI 0 "gpr_operand" "=r")(lo_sum:SI (const_int 0)(match_operand:SI 1 "move_src_operand" "i")))]"""mov %0, %%low(%1)"[(set_attr "type" "move")(set_attr "length" "4")])(define_insn_and_split "*movsi_insn"[(set (match_operand:SI 0 "move_dest_operand""= r, r, r, r, r, r, m, r, Rct")(match_operand:SI 1 "move_src_operand""rU16Rra,Cm1,Cl1,Cr1,Cal,mSra,rRra,Rct,r"))]"gpr_operand (operands[0], SImode)|| gpr_operand (operands[1], SImode)|| satisfies_constraint_Sra (operands[1])"{switch (which_alternative){case 0: return "mov %0,%1";case 1: return "add %0,%-,(1+%1)";case 2: operands[1] = GEN_INT (exact_log2 (-INTVAL (operands[1])));return "lsl %0,%-,%1";case 3: operands[1] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1));return "lsr %0,%-,%1";case 4: return "mov %0,%%low(%1)\;movt %0,%%high(%1) ; %1";case 5: return "ldr %0,%C1";case 6: return "str %1,%C0";case 7: return "movfs %0,%1";case 8: return "movts %0,%1";default: gcc_unreachable ();}}"reload_completed && CONSTANT_P (operands[1])&& !satisfies_constraint_U16 (operands[1])&& !satisfies_constraint_Cm1 (operands[1])&& !satisfies_constraint_Cl1 (operands[1])&& !satisfies_constraint_Cr1 (operands[1])&& TARGET_SPLIT_LOHI"[(match_dup 2) (match_dup 3)]"operands[2] = gen_movsi_lo_sum (operands[0], operands[1]);operands[3] = gen_movsi_high (operands[0], operands[1]);"[(set_attr "type" "move,misc,misc,misc,move,load,store,flow,flow")(set_attr "length" "4,4,4,4,8,4,4,4,4")])(define_split[(set (match_operand:SI 0 "nonimmediate_operand")(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR))]"reload_completed && !MACHINE_FUNCTION (cfun)->lr_clobbered"[(set (match_dup 0) (reg:SI GPR_LR))])(define_split[(set (match_operand:SI 0 "gpr_operand")(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR))]"reload_completed"[(set (match_dup 0) (match_dup 1))]{emit_insn (gen_reload_insi_ra (operands[0], operands[1]));DONE;})(define_expand "reload_insi_ra"[(set (match_operand:SI 0 "gpr_operand" "r") (match_operand:SI 1 "" "Sra"))]""{rtx addr= (frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx);addr = plus_constant (addr, MACHINE_FUNCTION (cfun)->lr_slot_offset);operands[1] = gen_frame_mem (SImode, addr);});; If the frame pointer elimination offset is zero, we'll use this pattern.;; Note that the splitter can accept any gpr in operands[1]; this is;; necessary, (e.g. for compile/20021015-1.c -O0,);; because when register elimination cannot be done with the constant;; as an immediate operand of the add instruction, reload will resort to;; loading the constant into a reload register, using gen_add2_insn to add;; the stack pointer, and then use the reload register as new source in;; the move_frame pattern.(define_insn_and_split "*move_frame_1"[(set (match_operand:SI 0 "gpr_operand" "=r")(match_operand:SI 1 "gpr_operand" "r"))(clobber (reg:CC CC_REGNUM))]"(reload_in_progress || reload_completed)&& (operands[1] == stack_pointer_rtx|| operands[1] == hard_frame_pointer_rtx)""#""reload_in_progress || reload_completed"[(set (match_dup 0) (match_dup 1))])(define_expand "mov<mode>"[(set (match_operand:DWMODE 0 "general_operand" "")(match_operand:DWMODE 1 "general_operand" ""))]"""{if (GET_MODE_CLASS (<MODE>mode) == MODE_VECTOR_INT|| GET_MODE_CLASS (<MODE>mode) == MODE_VECTOR_FLOAT){if (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY){rtx o0l, o0h, o1l, o1h;o0l = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);o0h = simplify_gen_subreg (SImode, operands[0], <MODE>mode,UNITS_PER_WORD);o1l = simplify_gen_subreg (SImode, operands[1], <MODE>mode, 0);o1h = simplify_gen_subreg (SImode, operands[1], <MODE>mode,UNITS_PER_WORD);if (reg_overlap_mentioned_p (o0l, o1h)){emit_move_insn (o0h, o1h);emit_move_insn (o0l, o1l);}else{emit_move_insn (o0l, o1l);emit_move_insn (o0h, o1h);}DONE;}/* lower_subreg has a tendency to muck up vectorized code.To protect the wide memory accesses, we must use same-sizesubregs. */if (epiphany_vect_align != 4 /* == 8 */&& !reload_in_progress&& (GET_CODE (operands[0]) == MEM || GET_CODE (operands[1]) == MEM)&& (GET_CODE (operands[0]) != SUBREG|| (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0])))!= GET_MODE_SIZE (<MODE>mode)&& GET_CODE (operands[1]) != SUBREG))){operands[0]= simplify_gen_subreg (DImode, operands[0], <MODE>mode, 0);operands[1]= simplify_gen_subreg (DImode, operands[1], <MODE>mode, 0);emit_insn (gen_movdi (operands[0], operands[1]));DONE;}}/* Everything except mem = const or mem = mem can be done easily. */if (GET_CODE (operands[0]) == MEM)operands[1] = force_reg (<MODE>mode, operands[1]);}")(define_insn_and_split "*mov<mode>_insn"[(set (match_operand:DWMODE 0 "move_dest_operand" "=r, r,r,m")(match_operand:DWMODE 1 "move_double_src_operand" "r,CalE,m,r"))]"(gpr_operand (operands[0], <MODE>mode)|| gpr_operand (operands[1], <MODE>mode))""@##ldrd %0,%X1strd %1,%X0""reload_completed&& ((!MEM_P (operands[0]) && !MEM_P (operands[1]))|| epiphany_vect_align == 4)"[(set (match_dup 2) (match_dup 3))(set (match_dup 4) (match_dup 5))]{int word0 = 0, word1 = UNITS_PER_WORD;if (post_modify_operand (operands[0], <MODE>mode)|| post_modify_operand (operands[1], <MODE>mode))word0 = UNITS_PER_WORD, word1 = 0;operands[2] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, word0);operands[3] = simplify_gen_subreg (SImode, operands[1], <MODE>mode, word0);operands[4] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, word1);operands[5] = simplify_gen_subreg (SImode, operands[1], <MODE>mode, word1);if (post_modify_operand (operands[0], <MODE>mode))operands[2]= change_address (operands[2], VOIDmode,plus_constant (XEXP (XEXP (operands[0], 0), 0),UNITS_PER_WORD));if (post_modify_operand (operands[1], <MODE>mode))operands[3]= change_address (operands[3], VOIDmode,plus_constant (XEXP (XEXP (operands[1], 0), 0),UNITS_PER_WORD));}[(set_attr "type" "move,move,load,store")(set_attr "length" "8,16,4,4")])(define_insn_and_split "*movsf_insn"[(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m")(match_operand:SF 1 "move_src_operand" "r,E,m,r"))]"gpr_operand (operands[0], SFmode)|| gpr_operand (operands[1], SFmode)""@mov %0,%1mov %0,%%low(%1)\;movt %0,%%high(%1) ; %1ldr %0,%C1str %1,%C0""reload_completed && CONSTANT_P (operands[1]) && TARGET_SPLIT_LOHI"[(set (match_dup 2) (match_dup 3))]"operands[2] = simplify_gen_subreg (SImode, operands[0], SFmode, 0);operands[3] = simplify_gen_subreg (SImode, operands[1], SFmode, 0);"[(set_attr "type" "move,move,load,store")(set_attr "length" "4,8,4,4")])(define_expand "addsi3"[(set (match_operand:SI 0 "add_reg_operand" "")(plus:SI (match_operand:SI 1 "add_reg_operand" "")(match_operand:SI 2 "add_operand" "")))]"""{if (reload_in_progress || reload_completed)emit_insn (gen_addsi3_r (operands[0], operands[1], operands[2]));elseemit_insn (gen_addsi3_i (operands[0], operands[1], operands[2]));DONE;}")(define_insn "addsi3_i"[(set (match_operand:SI 0 "add_reg_operand" "=r")(plus:SI (match_operand:SI 1 "add_reg_operand" "%r")(match_operand:SI 2 "add_operand" "rL")))(clobber (reg:CC CC_REGNUM))]"""add %0,%1,%2"[(set_attr "type" "misc")]); We use a clobber of UNKNOWN_REGNUM here so that the peephole optimizers; can identify the unresolved flags clobber problem, and also to; avoid unwanted matches.;; At -O0 / -O1 we don't peephole all instances away. We could get better; debug unwinding through the emitted code if we added a splitter.(define_insn "addsi3_r"[(set (match_operand:SI 0 "gpr_operand" "=r")(plus:SI (match_operand:SI 1 "gpr_operand" "%r")(match_operand:SI 2 "nonmemory_operand" "rCar")))(clobber (reg:CC UNKNOWN_REGNUM))]"reload_in_progress || reload_completed"{int scratch = (0x17^ (true_regnum (operands[0]) & 1)^ (true_regnum (operands[1]) & 2)^ (true_regnum (operands[2]) & 4));asm_fprintf (asm_out_file, "\tstr r%d,[sp,#0]\n", scratch);asm_fprintf (asm_out_file, "\tmovfs r%d,status\n", scratch);output_asm_insn ("add %0,%1,%2", operands);asm_fprintf (asm_out_file, "\tmovts status,r%d\n", scratch);asm_fprintf (asm_out_file, "\tldr r%d,[sp,#0]\n", scratch);return "";}[(set_attr "length" "20")(set_attr "type" "misc")]);; reload uses gen_addsi2 because it doesn't understand the need for;; the clobber.(define_peephole2[(set (match_operand:SI 0 "gpr_operand" "")(match_operand:SI 1 "const_int_operand" ""))(parallel [(set (match_dup 0)(plus:SI (match_dup 0)(match_operand:SI 2 "gpr_operand")))(clobber (reg:CC UNKNOWN_REGNUM))])]"satisfies_constraint_L (operands[1])|| ((operands[2] == stack_pointer_rtx|| (operands[2] == hard_frame_pointer_rtx && frame_pointer_needed))&& !peep2_regno_dead_p (2, CC_REGNUM)&& satisfies_constraint_Car (operands[1]))"[(parallel [(set (match_dup 0)(plus:SI (match_dup 2) (match_dup 1)))(clobber (reg:CC UNKNOWN_REGNUM))])];; FIXME:;; need this patch: http://gcc.gnu.org/ml/gcc-patches/2011-10/msg02819.html;; "peep2_rescan = true;")(define_peephole2[(match_parallel 5 ""[(set (match_operand 3 "cc_operand" "") (match_operand 4 "" ""))])(parallel [(set (match_operand:SI 0 "gpr_operand" "")(plus:SI (match_operand:SI 1 "gpr_operand" "")(match_operand:SI 2 "nonmemory_operand" "")))(clobber (reg:CC UNKNOWN_REGNUM))])]"REGNO (operands[3]) == CC_REGNUM&& (gpr_operand (operands[2], SImode)|| satisfies_constraint_L (operands[2]))&& !reg_overlap_mentioned_p (operands[0], operands[5])&& !reg_set_p (operands[1], operands[5])&& !reg_set_p (operands[2], operands[5])"[(parallel [(set (match_operand:SI 0 "gpr_operand" "")(plus:SI (match_operand:SI 1 "gpr_operand" "")(match_operand:SI 2 "nonmemory_operand" "")))(clobber (reg:CC CC_REGNUM))])(match_dup 5)]"")(define_peephole2[(parallel [(set (match_operand:SI 0 "gpr_operand" "")(plus:SI (match_operand:SI 1 "gpr_operand" "")(match_operand:SI 2 "nonmemory_operand" "")))(clobber (reg:CC UNKNOWN_REGNUM))])]"peep2_regno_dead_p (1, CC_REGNUM)&& (gpr_operand (operands[2], SImode)|| satisfies_constraint_L (operands[2]))"[(parallel [(set (match_operand:SI 0 "gpr_operand" "")(plus:SI (match_operand:SI 1 "gpr_operand" "")(match_operand:SI 2 "nonmemory_operand" "")))(clobber (reg:CC CC_REGNUM))])]"")(define_peephole2[(parallel [(set (match_operand:SI 0 "gpr_operand" "")(plus:SI (reg:SI GPR_SP)(match_operand:SI 1 "nonmemory_operand" "")))(clobber (reg:CC UNKNOWN_REGNUM))])]"(REG_P (operands[1]) && !reg_overlap_mentioned_p (operands[0], operands[1]))|| RTX_OK_FOR_OFFSET_P (<MODE>mode, operands[1])"[(set (match_dup 0) (reg:SI GPR_SP))(set (mem:WMODE (post_modify (match_dup 0)(plus:SI (match_dup 0) (match_dup 1))))(reg:WMODE GPR_SP))]"")(define_peephole2[(parallel [(set (match_operand:SI 0 "gpr_operand" "")(plus:SI (reg:SI GPR_FP)(match_operand:SI 1 "nonmemory_operand" "")))(clobber (reg:CC UNKNOWN_REGNUM))])(match_scratch:WMODE 2 "r")]"frame_pointer_needed&& ((REG_P (operands[1])&& !reg_overlap_mentioned_p (operands[0], operands[1]))|| RTX_OK_FOR_OFFSET_P (<MODE>mode, operands[1]))"[(set (match_dup 0) (reg:SI GPR_FP))(set (match_dup 2)(mem:WMODE (post_modify (match_dup 0)(plus:SI (match_dup 0) (match_dup 1)))))]"")(define_insn "subsi3"[(set (match_operand:SI 0 "gpr_operand" "=r")(minus:SI (match_operand:SI 1 "add_reg_operand" "r")(match_operand:SI 2 "arith_operand" "rL")))(clobber (reg:CC CC_REGNUM))]"""sub %0,%1,%2"[(set_attr "type" "misc")]); After mode-switching, floating point operations, fp_sfuncs and calls; must exhibit the use of the control register, lest the setting of the; control register could be deleted or moved. OTOH a use of a hard register; greatly coundounds optimizers like the rtl loop optimizers or combine.; Therefore, we put an extra pass immediately after the mode switching pass; that inserts the USEs of the control registers, and sets a flag in struct; machine_function that float_operation can henceforth only match with that; USE.;; Addition(define_expand "addsf3"[(parallel[(set (match_operand:SF 0 "gpr_operand" "")(plus:SF (match_operand:SF 1 "gpr_operand" "")(match_operand:SF 2 "gpr_operand" "")))(clobber (reg:CC_FP CCFP_REGNUM))])])(define_insn "*addsf3_i"[(match_parallel 3 "float_operation"[(set (match_operand:SF 0 "gpr_operand" "=r")(plus:SF (match_operand:SF 1 "gpr_operand" "%r")(match_operand:SF 2 "gpr_operand" "r")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""fadd %0,%1,%2"[(set_attr "type" "fp")]);; Subtraction(define_expand "subsf3"[(parallel[(set (match_operand:SF 0 "gpr_operand" "")(minus:SF (match_operand:SF 1 "gpr_operand" "")(match_operand:SF 2 "gpr_operand" "")))(clobber (reg:CC_FP CCFP_REGNUM))])])(define_insn "*subsf3_i"[(match_parallel 3 "float_operation"[(set (match_operand:SF 0 "gpr_operand" "=r")(minus:SF (match_operand:SF 1 "gpr_operand" "r")(match_operand:SF 2 "gpr_operand" "r")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""fsub %0,%1,%2"[(set_attr "type" "fp")])(define_expand "subsf3_f"[(parallel[(set (reg:CC_FP CCFP_REGNUM)(compare:CC_FP (match_operand:SF 1 "gpr_operand" "r")(match_operand:SF 2 "gpr_operand" "r")))(set (match_operand:SF 0 "gpr_operand" "=r")(minus:SF (match_dup 1) (match_dup 2)))])]"!TARGET_SOFT_CMPSF")(define_insn "*subsf3_f_i"[(match_parallel 3 "float_operation"[(set (reg:CC_FP CCFP_REGNUM)(compare:CC_FP (match_operand:SF 1 "gpr_operand" "r")(match_operand:SF 2 "gpr_operand" "r")))(set (match_operand:SF 0 "gpr_operand" "=r")(minus:SF (match_dup 1) (match_dup 2)))])]"!TARGET_SOFT_CMPSF""fsub %0,%1,%2"[(set_attr "type" "fp")]); There is an fabs instruction, but it has longer latency.(define_expand "abssf2"[(set (match_operand:SF 0 "gpr_operand" "")(abs:SF (match_operand:SF 1 "gpr_operand" "")))]"""{rtx op1 = copy_to_mode_reg (SImode, simplify_gen_subreg (SImode, operands[1],SFmode, 0));rtx op0 = simplify_gen_subreg (SImode, operands[0], SFmode, 0);emit_insn (gen_ashlsi3 (op1, op1, const1_rtx));emit_insn (gen_lshrsi3 (op0, op1, const1_rtx));DONE;}");; Multiplication(define_expand "mulsf3"[(parallel[(set (match_operand:SF 0 "gpr_operand" "")(mult:SF (match_operand:SF 1 "gpr_operand" "")(match_operand:SF 2 "gpr_operand" "")))(clobber (reg:CC_FP CCFP_REGNUM))])])(define_insn "*mulsf3_i"[(match_parallel 3 "float_operation"[(set (match_operand:SF 0 "gpr_operand" "=r")(mult:SF (match_operand:SF 1 "gpr_operand" "%r")(match_operand:SF 2 "gpr_operand" "r")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""fmul %0,%1,%2"[(set_attr "type" "fp")]);; Division(define_expand "divsf3"[(set (match_operand:SF 0 "gpr_operand" "")(div:SF (match_operand:SF 1 "gpr_operand" "")(match_operand:SF 2 "gpr_operand" "")))]"flag_reciprocal_math"{rtx one = CONST1_RTX (SFmode);rtx dst = operands[0];if (rtx_equal_p (dst, operands[1])){emit_move_insn (dst, one);DONE;}else if (!register_operand (dst, SFmode) && can_create_pseudo_p ())dst = gen_reg_rtx (SFmode);emit_insn (gen_recipsf2 (dst, one, operands[2],sfunc_symbol (\"__fast_recipsf2\")));emit_insn (gen_mulsf3 (operands[0], operands[1], dst));DONE;});; Before reload, keep the hard reg usage to clobbers so that the loop;; optimizers can more easily move this insn.;; It would be nicer to use a constraint for a GPR_0 - only register class,;; but sched1 can still cause trouble then, and there is no guarantee of;; better register allocations.;; Neither is there when using the opposite strategy - putting explicit;; hard register references into pre-reload rtl.(define_expand "recipsf2"[(parallel[(set (match_operand:SF 0 "gpr_operand" "")(div:SF (match_operand:SF 1 "const_float_1_operand" "")(match_operand:SF 2 "move_src_operand" "")))(use (match_operand:SI 3 "move_src_operand" ""))(clobber (reg:SF 0))(clobber (reg:SI 1))(clobber (reg:SF GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:DI GPR_18))(clobber (reg:SI GPR_20))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])])(define_insn_and_split "*recipsf2_1"[(match_parallel 4 "float_operation"[(set (match_operand:SF 0 "gpr_operand" "=r,r")(div:SF (match_operand:SF 1 "const_float_1_operand" "")(match_operand:SF 2 "move_src_operand" "rU16m,rU16mCal")))(use (match_operand:SI 3 "move_src_operand" "rU16m,rU16mCal"))(clobber (reg:SF 0))(clobber (reg:SI 1))(clobber (reg:SF GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:DI GPR_18))(clobber (reg:SI GPR_20))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"flag_reciprocal_math""#""&& reload_completed"[(set (reg:SI 1) (match_dup 3))(set (reg:SF 0) (match_dup 2))(parallel[(set (reg:SF 0)(div:SF (match_dup 1)(reg:SF 0)))(use (reg:SI 1))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:DI GPR_18))(clobber (reg:SI GPR_20))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))(match_dup 5)(match_dup 6)])(set (match_dup 0) (reg:SF 0))]"operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"[(set_attr "type" "fp_sfunc")(set_attr "length" "16,24")])(define_insn "*recipsf2_2"[(match_parallel 1 "float_operation"[(set (reg:SF 0)(div:SF (match_operand:SF 0 "const_float_1_operand" "")(reg:SF 0)))(use (reg:SI 1))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:DI GPR_18))(clobber (reg:SI GPR_20))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"flag_reciprocal_math""jalr r1"[(set_attr "type" "fp_sfunc")]);; Fused multiply-add(define_expand "fmasf4"[(parallel[(set (match_operand:SF 0 "gpr_operand" "")(fma:SF (match_operand:SF 1 "gpr_operand" "")(match_operand:SF 2 "gpr_operand" "")(match_operand:SF 3 "gpr_operand" "")))(clobber (reg:CC_FP CCFP_REGNUM))])]""); The multiply operands are commutative, but since they have the; same constraints, there is no point in telling reload about this.(define_insn "*fmadd"[(match_parallel 4 "float_operation"[(set (match_operand:SF 0 "gpr_operand" "=r")(fma:SF (match_operand:SF 1 "gpr_operand" "r")(match_operand:SF 2 "gpr_operand" "r")(match_operand:SF 3 "gpr_operand" "0")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""fmadd %0,%1,%2"[(set_attr "type" "fp")]); Once vetorization consistently works for this port, should check; if the fmadd / fmsub patterns still serve a purpose. With the; introduction of fma / fnma handling by the SSA optimizers,; at least scalars should be handled by these optimizers, would; have to see how well they do on vectors from auto-vectorization.;; combiner pattern, also used by vector combiner pattern(define_expand "maddsf"[(parallel[(set (match_operand:SF 0 "gpr_operand" "=r")(plus:SF (mult:SF (match_operand:SF 1 "gpr_operand" "r")(match_operand:SF 2 "gpr_operand" "r"))(match_operand:SF 3 "gpr_operand" "0")))(clobber (reg:CC_FP CCFP_REGNUM))])]"TARGET_FUSED_MADD")(define_insn "*maddsf_combine"[(match_parallel 4 "float_operation"[(set (match_operand:SF 0 "gpr_operand" "=r")(plus:SF (mult:SF (match_operand:SF 1 "gpr_operand" "r")(match_operand:SF 2 "gpr_operand" "r"))(match_operand:SF 3 "gpr_operand" "0")))(clobber (reg:CC_FP CCFP_REGNUM))])]"TARGET_FUSED_MADD""fmadd %0,%1,%2"[(set_attr "type" "fp")]);; Fused multiply-sub(define_expand "fnmasf4"[(parallel[(set (match_operand:SF 0 "gpr_operand" "")(fma:SF (neg:SF (match_operand:SF 1 "gpr_operand" ""))(match_operand:SF 2 "gpr_operand" "")(match_operand:SF 3 "gpr_operand" "")))(clobber (reg:CC_FP CCFP_REGNUM))])]"")(define_insn "*fmsub"[(match_parallel 4 "float_operation"[(set (match_operand:SF 0 "gpr_operand" "=r")(fma:SF (neg:SF (match_operand:SF 1 "gpr_operand" "r"))(match_operand:SF 2 "gpr_operand" "r")(match_operand:SF 3 "gpr_operand" "0")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""fmsub %0,%1,%2"[(set_attr "type" "fp")])(define_insn "*fmsub_combine"[(match_parallel 4 "float_operation"[(set (match_operand:SF 0 "gpr_operand" "=r")(minus:SF (match_operand:SF 3 "gpr_operand" "0")(mult:SF (match_operand:SF 1 "gpr_operand" "r")(match_operand:SF 2 "gpr_operand" "r"))))(clobber (reg:CC_FP CCFP_REGNUM))])]"TARGET_FUSED_MADD""fmsub %0,%1,%2"[(set_attr "type" "fp")]);; float / integer conversions(define_expand "floatsisf2"[(parallel[(set (match_operand:SF 0 "gpr_operand" "")(float:SF (match_operand:SI 1 "gpr_operand" "")))(clobber (reg:CC_FP CCFP_REGNUM))])])(define_insn "*floatsisf2_i"[(match_parallel 2 "float_operation"[(set (match_operand:SF 0 "gpr_operand" "=r")(float:SF (match_operand:SI 1 "gpr_operand" "r")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""float %0, %1"[(set_attr "type" "fp")])(define_expand "floatsisf2_cmp"[(parallel[(set (reg:CC_FP CCFP_REGNUM)(compare:CC_FP (float:SF (match_operand:SF 1 "gpr_operand" "r"))(match_dup 2)))(set (match_operand:SF 0 "gpr_operand" "=r")(float:SF (match_dup 1)))])]"""operands[2] = CONST0_RTX (SFmode);")(define_insn "*floatsisf2_cmp_i"[(match_parallel 3 "float_operation"[(set (reg:CC_FP CCFP_REGNUM)(compare:CC_FP (float:SF (match_operand:SF 1 "gpr_operand" "r"))(match_operand:SF 2 "const0_operand" "")))(set (match_operand:SF 0 "gpr_operand" "=r")(float:SF (match_dup 1)))])]"""float %0, %1"[(set_attr "type" "fp")])(define_expand "floatunssisf2"[(set (match_operand:SF 0 "gpr_operand" "")(float:SF (match_operand:SI 1 "gpr_operand" "")))]"epiphany_normal_fp_rounding == /*FP_MODE_ROUND_TRUNC*/ 2"{rtx cst = force_reg (SImode, gen_int_mode (0xb0800000, SImode));rtx tmp = gen_reg_rtx (SImode);rtx cmp = gen_rtx_GTU (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx);if (reg_overlap_mentioned_p (operands[0], operands[1]))operands[1] = copy_to_mode_reg (SImode, operands[1]);emit_insn (gen_floatsisf2 (operands[0], operands[1]));emit_insn (gen_ashrsi3 (tmp, operands[1], GEN_INT (8)));emit_insn (gen_sub_f (tmp, tmp, cst));emit_insn (gen_movsfcc (operands[0], cmp,simplify_gen_subreg (SFmode, tmp, SImode, 0),operands[0]));DONE;})(define_expand "fix_truncsfsi2"[(parallel[(set (match_operand:SI 0 "gpr_operand" "")(fix:SI (match_operand:SF 1 "gpr_operand" "")))(clobber (reg:CC_FP CCFP_REGNUM))])])(define_insn "*fix_truncsfsi2_i"[(match_parallel 2 "float_operation"[(set (match_operand:SI 0 "gpr_operand" "=r")(fix:SI (match_operand:SF 1 "gpr_operand" "r")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""fix %0, %1"[(set_attr "type" "fp")(set_attr "fp_mode" "round_trunc")])(define_expand "fixuns_truncsfsi2"[(set (match_operand:SI 0 "gpr_operand" "")(unsigned_fix:SI (match_operand:SF 1 "gpr_operand" "")))]""{if (reg_overlap_mentioned_p (operands[0], operands[1]))operands[1] = copy_to_mode_reg (SImode, operands[1]);if (TARGET_SOFT_CMPSF || optimize_function_for_speed_p (cfun)){rtx op1si;/* By toggling what it to be bit31 before the shift, we get a chance touse a short movt insn. */rtx bit31 = force_reg (SImode, GEN_INT (0x800000));rtx tmp = gen_reg_rtx (SImode);rtx limit = force_reg (SImode, gen_int_mode (0x4f000000, SImode));rtx cmp= gen_rtx_GE (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx);op1si = simplify_gen_subreg (SImode, operands[1], SFmode, 0);emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));emit_insn (gen_subsi3 (tmp, op1si, bit31));emit_insn (gen_ashlsi3 (tmp, tmp, GEN_INT (8)));emit_insn (gen_cmpsi_cc_insn (op1si, limit));emit_insn (gen_movsicc (operands[0], cmp, tmp, operands[0]));}else{REAL_VALUE_TYPE offset;rtx limit;rtx tmp = gen_reg_rtx (SFmode);rtx label = gen_label_rtx ();rtx bit31;rtx cc1 = gen_rtx_REG (CC_FPmode, CCFP_REGNUM);rtx cmp = gen_rtx_LT (VOIDmode, cc1, CONST0_RTX (SFmode));real_2expN (&offset, 31, SFmode);limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode);limit = force_reg (SFmode, limit);emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));emit_insn (gen_subsf3_f (tmp, operands[1], limit));emit_jump_insn (gen_branch_insn (label, cmp, cc1));bit31 = force_reg (SImode, gen_int_mode (0x80000000, SImode));emit_insn (gen_fix_truncsfsi2 (operands[0], tmp));emit_insn (gen_xorsi3 (operands[0], operands[0], bit31));emit_label (label);}DONE;})(define_insn "*iadd"[(match_parallel 3 "float_operation"[(set (match_operand:SI 0 "gpr_operand" "=r")(plus:SI (match_operand:SI 1 "gpr_operand" "%r")(match_operand:SI 2 "gpr_operand" "r")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""iadd %0, %1, %2"[(set_attr "type" "fp_int")])(define_insn "*isub"[(match_parallel 3 "float_operation"[(set (match_operand:SI 0 "gpr_operand" "=r")(minus:SI (match_operand:SI 1 "gpr_operand" "r")(match_operand:SI 2 "gpr_operand" "r")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""isub %0, %1, %2"[(set_attr "type" "fp_int")])(define_expand "mulsi3"[(parallel[(set (match_operand:SI 0 "gpr_operand" "")(mult:SI (match_operand:SI 1 "gpr_operand" "")(match_operand:SI 2 "gpr_operand" "")))(clobber (reg:CC_FP CCFP_REGNUM))])])(define_insn "*imul"[(match_parallel 3 "float_operation"[(set (match_operand:SI 0 "gpr_operand" "=r")(mult:SI (match_operand:SI 1 "gpr_operand" "%r")(match_operand:SI 2 "gpr_operand" "r")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""imul %0, %1, %2"[(set_attr "type" "fp_int")]); combiner pattern, also used by vector combiner pattern(define_expand "maddsi"[(parallel[(set (match_operand:SI 0 "gpr_operand" "=r")(plus:SI (mult:SI (match_operand:SI 1 "gpr_operand" "r")(match_operand:SI 2 "gpr_operand" "r"))(match_operand:SI 3 "gpr_operand" "0")))(clobber (reg:CC_FP CCFP_REGNUM))])]"")(define_insn "*maddsi_combine"[(match_parallel 4 "float_operation"[(set (match_operand:SI 0 "gpr_operand" "=r")(plus:SI (mult:SI (match_operand:SI 1 "gpr_operand" "r")(match_operand:SI 2 "gpr_operand" "r"))(match_operand:SI 3 "gpr_operand" "0")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""imsub %0, %1, %2"[(set_attr "type" "fp_int")])(define_insn "*imsub"[(match_parallel 4 "float_operation"[(set (match_operand:SI 0 "gpr_operand" "=r")(minus:SI (match_operand:SI 3 "gpr_operand" "0")(mult:SI (match_operand:SI 1 "gpr_operand" "r")(match_operand:SI 2 "gpr_operand" "r"))))(clobber (reg:CC_FP CCFP_REGNUM))])]"""imsub %0, %1, %2"[(set_attr "type" "fp_int")])(define_expand "divsi3"[(parallel[(set (match_operand:SI 0 "move_dest_operand" "")(div:SI (match_operand:SI 1 "move_src_operand" "")(match_operand:SI 2 "move_src_operand" "")))(use (match_dup 3))(clobber (reg:SI 0))(clobber (reg:SI 1))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:DI GPR_18))(clobber (reg:SI GPR_20))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"""operands[3] = sfunc_symbol (\"__divsi3\");");; Before reload, keep the hard reg usage to clobbers so that the loop;; optimizers can more easily move this insn.(define_insn_and_split "*divsi3_1"[(match_parallel 4 "float_operation"[(set (match_operand:SI 0 "move_dest_operand" "=r,r")(div:SI (match_operand:SI 1 "move_src_operand" "rU16m,rU16mCal")(match_operand:SI 2 "move_src_operand" "rU16m,rU16mCal")))(use (match_operand:SI 3 "call_address_operand" "Csy,r"))(clobber (reg:SI 0))(clobber (reg:SI 1))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:DI GPR_18))(clobber (reg:SI GPR_20))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"""#""&& reload_completed"[(set (reg:SI 0) (match_dup 1))(set (reg:SI 1) (match_dup 2))(parallel[(set (reg:SI 0) (div:SI (reg:SI 0) (reg:SI 1)))(use (match_dup 3))(clobber (reg:SI 1))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:DI GPR_18))(clobber (reg:SI GPR_20))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))(match_dup 5)(match_dup 6)])(set (match_dup 0) (reg:SI 0))]"operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"[(set_attr "type" "fp_sfunc")(set_attr "length" "16,24")])(define_insn "*divsi3_2"[(match_parallel 1 "float_operation"[(set (reg:SI 0) (div:SI (reg:SI 0) (reg:SI 1)))(use (match_operand:SI 0 "call_address_operand" "Csy,r"))(clobber (reg:SI 1))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:DI GPR_18))(clobber (reg:SI GPR_20))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"""%f0"[(set_attr "type" "fp_sfunc")])(define_expand "udivsi3"[(parallel[(set (match_operand:SI 0 "move_dest_operand" "")(udiv:SI (match_operand:SI 1 "move_src_operand" "")(match_operand:SI 2 "move_src_operand" "")))(use (match_dup 3))(clobber (reg:SI 0))(clobber (reg:SI 1))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:SI GPR_18))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"""operands[3] = sfunc_symbol (\"__udivsi3\");");; Before reload, keep the hard reg usage to clobbers so that the loop;; optimizers can more easily move this insn.(define_insn_and_split "*udivsi3_1"[(match_parallel 4 "float_operation"[(set (match_operand:SI 0 "move_dest_operand" "=r,r")(udiv:SI (match_operand:SI 1 "move_src_operand" "rU16m,rU16mCal")(match_operand:SI 2 "move_src_operand" "rU16m,rU16mCal")))(use (match_operand:SI 3 "call_address_operand" "Csy,r"))(clobber (reg:SI 0))(clobber (reg:SI 1))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:SI GPR_18))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"""#""&& reload_completed"[(set (reg:SI 0) (match_dup 1))(set (reg:SI 1) (match_dup 2))(parallel[(set (reg:SI 0) (udiv:SI (reg:SI 0) (reg:SI 1)))(use (match_dup 3))(clobber (reg:SI 1))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:SI GPR_18))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))(match_dup 5)(match_dup 6)])(set (match_dup 0) (reg:SI 0))]"operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"[(set_attr "type" "fp_sfunc")(set_attr "length" "16,24")])(define_insn "*udivsi3_2"[(match_parallel 1 "float_operation"[(set (reg:SI 0) (udiv:SI (reg:SI 0) (reg:SI 1)))(use (match_operand:SI 0 "call_address_operand" "Csy,r"))(clobber (reg:SI 1))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:SI GPR_18))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"""%f0"[(set_attr "type" "fp_sfunc")])(define_expand "modsi3"[(parallel[(set (match_operand:SI 0 "move_dest_operand" "")(mod:SI (match_operand:SI 1 "move_src_operand" "")(match_operand:SI 2 "move_src_operand" "")))(use (match_dup 3))(clobber (reg:SI 0))(clobber (reg:SI 1))(clobber (reg:SI 2))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:DI GPR_18))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"""operands[3] = sfunc_symbol (\"__modsi3\");");; Before reload, keep the hard reg usage to clobbers so that the loop;; optimizers can more easily move this insn.(define_insn_and_split "*modsi3_1"[(match_parallel 4 "float_operation"[(set (match_operand:SI 0 "move_dest_operand" "=r,r")(mod:SI (match_operand:SI 1 "move_src_operand" "rU16m,rU16mCal")(match_operand:SI 2 "move_src_operand" "rU16m,rU16mCal")))(use (match_operand:SI 3 "call_address_operand" "Csy,r"))(clobber (reg:SI 0))(clobber (reg:SI 1))(clobber (reg:SI 2))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:DI GPR_18))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"""#""&& reload_completed"[(set (reg:SI 0) (match_dup 1))(set (reg:SI 1) (match_dup 2))(parallel[(set (reg:SI 0) (mod:SI (reg:SI 0) (reg:SI 1)))(use (match_dup 3))(clobber (reg:SI 2))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:DI GPR_18))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))(match_dup 5)(match_dup 6)])(set (match_dup 0) (reg:SI 0))]"operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"[(set_attr "type" "fp_sfunc")(set_attr "length" "16,24")])(define_insn "*modsi3_2"[(match_parallel 1 "float_operation"[(set (reg:SI 0) (mod:SI (reg:SI 0) (reg:SI 1)))(use (match_operand:SI 0 "call_address_operand" "Csy,r"))(clobber (reg:SI 2))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:DI GPR_18))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"""%f0"[(set_attr "type" "fp_sfunc")])(define_expand "umodsi3"[(parallel[(set (match_operand:SI 0 "move_dest_operand" "")(umod:SI (match_operand:SI 1 "move_src_operand" "")(match_operand:SI 2 "move_src_operand" "")))(use (match_dup 3))(clobber (reg:SI 0))(clobber (reg:SI 1))(clobber (reg:SI 2))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"""operands[3] = sfunc_symbol (\"__umodsi3\");");; Before reload, keep the hard reg usage to clobbers so that the loop;; optimizers can more easily move this insn.(define_insn_and_split "*umodsi3_1"[(match_parallel 4 "float_operation"[(set (match_operand:SI 0 "move_dest_operand" "=r,r")(umod:SI (match_operand:SI 1 "move_src_operand" "rU16m,rU16mCal")(match_operand:SI 2 "move_src_operand" "rU16m,rU16mCal")))(use (match_operand:SI 3 "call_address_operand" "Csy,r"))(clobber (reg:SI 0))(clobber (reg:SI 1))(clobber (reg:SI 2))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"""#""&& reload_completed"[(set (reg:SI 0) (match_dup 1))(set (reg:SI 1) (match_dup 2))(parallel[(set (reg:SI 0) (umod:SI (reg:SI 0) (reg:SI 1)))(use (match_dup 3))(clobber (reg:SI 2))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))(match_dup 5)(match_dup 6)])(set (match_dup 0) (reg:SI 0))]"operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"[(set_attr "type" "fp_sfunc")(set_attr "length" "16,24")])(define_insn "*umodsi3_2"[(match_parallel 1 "float_operation"[(set (reg:SI 0) (umod:SI (reg:SI 0) (reg:SI 1)))(use (match_operand:SI 0 "call_address_operand" "Csy,r"))(clobber (reg:SI 2))(clobber (reg:SI GPR_IP))(clobber (reg:DI GPR_16))(clobber (reg:SI GPR_LR))(clobber (reg:CC CC_REGNUM))(clobber (reg:CC_FP CCFP_REGNUM))])]"""%f0"[(set_attr "type" "fp_sfunc")]); Disable interrupts.; Any earlier values read from CONFIG_REGNUM are out of date, since interrupts; might have changed settings that we do not want to mess with.(define_insn "gid"[(set (reg:SI CONFIG_REGNUM)(unspec_volatile:SI [(const_int 0)] UNSPECV_GID))]"""gid"[(set_attr "type" "flow")]); Enable interrupts.; Present CONTROL_REGNUM here to make sure it is live before the; actual uses in floating point insns / calls are inserted.; FWIW, interrupts also do mind what is in the control register.(define_insn "gie"[(unspec_volatile [(reg:SI CONFIG_REGNUM)] UNSPECV_GIE)]"""gie"[(set_attr "type" "flow")]); Floating point instructions require manipulating the control register.; Manipulating the control register needs aritmetic.; Arithmetic clobbers flags.; The flags are in the status register, which also contains the alternate; flag and the interrupt enable/disable bits.; saving/restoring status and mixing up the order with gid/gie could; lead to disaster.; Usually, saving/restoring the status is unnecessary, and will be optimized; away. But when we really need it, we must make sure that we don't change; anything but the flags.; N.B.: We could make the constant easier to load by inverting it, but; then we'd need to clobber the saved value - and that would make optimizing; away unneeded saves/restores harder / less likely.(define_expand "movcc"[(parallel [(set (match_operand:CC 0 "cc_move_operand" "")(match_operand:CC 1 "cc_move_operand" ""))(use (match_dup 2))(clobber (match_scratch:SI 3 "=X, &r"))])]"""operands[2] = gen_int_mode (~0x10f0, SImode);")(define_insn "*movcc_i"[(set (match_operand:CC 0 "cc_move_operand" "=r,Rcc")(match_operand:CC 1 "cc_move_operand" "Rcc, r"))(use (match_operand:SI 2 "nonmemory_operand" "X, r"))(clobber (match_scratch:SI 3 "=X, &r"))]"""@movfs %0,statusmovfs %3,status\;eor %3,%3,%1\;and %3,%3,%2\;eor %3,%3,%1\;movts status,%3"[(set_attr "type" "flow")(set_attr "length" "20,4")])(define_insn_and_split "set_fp_mode"[(set (reg:SI FP_NEAREST_REGNUM)(match_operand:SI 0 "set_fp_mode_operand" "rCfm"))(set (reg:SI FP_TRUNCATE_REGNUM) (match_dup 0))(set (reg:SI FP_ANYFP_REGNUM)(match_operand:SI 1 "set_fp_mode_operand" "rCfm"))(use (match_operand:SI 2 "gpr_operand" "r"))(clobber (reg:CC CC_REGNUM))(clobber (match_scratch:SI 3 "=&r"))]"""#""reload_completed || !rtx_equal_p (operands[0], operands[1])"[(const_int 0)]{if (!reload_completed)emit_note (NOTE_INSN_DELETED);elseepiphany_expand_set_fp_mode (operands);DONE;});; Boolean instructions.;;;; We don't define the DImode versions as expand_binop does a good enough job.(define_insn "andsi3"[(set (match_operand:SI 0 "gpr_operand" "=r")(and:SI (match_operand:SI 1 "gpr_operand" "r")(match_operand:SI 2 "gpr_operand" "r")))(clobber (reg:CC CC_REGNUM))]"""and %0,%1,%2")(define_insn "iorsi3"[(set (match_operand:SI 0 "gpr_operand" "=r")(ior:SI (match_operand:SI 1 "gpr_operand" "r")(match_operand:SI 2 "gpr_operand" "r")))(clobber (reg:CC CC_REGNUM))]"""orr %0,%1,%2")(define_insn "xorsi3"[(set (match_operand:SI 0 "gpr_operand" "=r")(xor:SI (match_operand:SI 1 "gpr_operand" "r")(match_operand:SI 2 "gpr_operand" "r")))(clobber (reg:CC CC_REGNUM))]"""eor %0,%1,%2")(define_expand "one_cmplsi2"[(set (match_operand:SI 0 "gpr_operand" "")(xor:SI (match_operand:SI 1 "gpr_operand" "")(match_dup 2)))]""{if (epiphany_m1reg >= 0)emit_insn (gen_one_cmplsi2_i (operands[0], operands[1]));elseemit_insn (gen_xorsi3 (operands[0], operands[1],force_reg (SImode, GEN_INT (-1))));DONE;}); Note that folding this pattern into the xorsi3 pattern would make combine; less effective.(define_insn "one_cmplsi2_i"[(set (match_operand:SI 0 "gpr_operand" "=r")(not:SI (match_operand:SI 1 "gpr_operand" "r")))(clobber (reg:CC CC_REGNUM))]"epiphany_m1reg >= 0""eor %0,%1,%-");; Shift instructions.;; In principle we could support arbitrary symbolic values as shift constant;; (truncating the value appropriately), but that would require a suitable;; relocation and assembler & linker support.(define_insn "ashrsi3"[(set (match_operand:SI 0 "gpr_operand" "=r,r")(ashiftrt:SI (match_operand:SI 1 "gpr_operand" "r,r")(match_operand:SI 2 "arith_operand" "r,K")))(clobber (reg:CC CC_REGNUM))]"""asr %0,%1,%2"[(set_attr "length" "4")(set_attr "type" "shift")])(define_insn "ashrsi3_tst"[(set (reg:CC CC_REGNUM)(compare:CC(ashiftrt:SI (match_operand:SI 1 "gpr_operand" "r,r")(match_operand:SI 2 "arith_operand" "r,K"))(const_int 0)))(set (match_operand:SI 0 "gpr_operand" "=r,r")(ashiftrt:SI (match_dup 1) (match_dup 2)))]"""asr %0,%1,%2"[(set_attr "length" "4")(set_attr "type" "shift")]);; Logical Shift Right(define_insn "lshrsi3"[(set (match_operand:SI 0 "gpr_operand" "=r,r")(lshiftrt:SI (match_operand:SI 1 "gpr_operand" "r,r")(match_operand:SI 2 "arith_operand" "r,K")))(clobber (reg:CC CC_REGNUM))]"""lsr %0,%1,%2"[(set_attr "length" "4")(set_attr "type" "shift")])(define_insn "lshrsi3_tst"[(set (reg:CC CC_REGNUM)(compare:CC(lshiftrt:SI (match_operand:SI 1 "gpr_operand" "r,r")(match_operand:SI 2 "arith_operand" "r,K"))(const_int 0)))(set (match_operand:SI 0 "gpr_operand" "=r,r")(lshiftrt:SI (match_dup 1) (match_dup 2)))]"""lsr %0,%1,%2"[(set_attr "length" "4")(set_attr "type" "shift")]);; Logical/Arithmetic Shift Left(define_insn "ashlsi3"[(set (match_operand:SI 0 "gpr_operand" "=r,r")(ashift:SI (match_operand:SI 1 "gpr_operand" "r,r")(match_operand:SI 2 "arith_operand" "r,K")))(clobber (reg:CC CC_REGNUM))]"""lsl %0,%1,%2"[(set_attr "length" "4")(set_attr "type" "shift")])(define_insn "*ashlsi_btst"[(set (reg:CC_N_NE CC_REGNUM)(compare:CC_N_NE(zero_extract:SI (match_operand:SI 1 "gpr_operand" "r")(const_int 1)(match_operand 2 "const_int_operand" "K"))(const_int 0)))(clobber (match_scratch:SI 0 "=r"))]""{rtx xop[3];xop[0] = operands[0];xop[1] = operands[1];xop[2] = GEN_INT (31-INTVAL (operands[2]));output_asm_insn ("lsl %0,%1,%2", xop);return "";});; zero extensions(define_insn_and_split "zero_extendqisi2"[(set (match_operand:SI 0 "register_operand" "=r,r")(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))(clobber (reg:CC CC_REGNUM))]"""@#ldrb %0,%1""reload_completed? true_regnum (operands[1]) >= 0: REG_P (operands[1]) && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER"[(parallel [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))(clobber (reg:CC CC_REGNUM))])(parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))(clobber (reg:CC CC_REGNUM))])]"operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);")(define_insn "zero_extendhisi2"[(set (match_operand:SI 0 "register_operand" "=r,r")(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,m")))]"""@movt %0, 0ldrh %0,%c1");; Compare instructions.(define_insn "cmpsi_cc_insn"[(set (reg:CC CC_REGNUM)(compare:CC (match_operand:SI 0 "add_reg_operand" "r,r")(match_operand:SI 1 "arith_operand" "r,L")))(clobber (match_scratch:SI 2 "=r,r"))]"""sub %2,%0,%1"[(set_attr "type" "compare")])(define_insn "sub_f"[(set (reg:CC CC_REGNUM)(compare:CC (match_operand:SI 1 "gpr_operand" "r,r")(match_operand:SI 2 "arith_operand" "r,L")))(set (match_operand:SI 0 "gpr_operand" "=r,r")(minus:SI (match_dup 1) (match_dup 2)))]"""sub %0,%1,%2"[(set_attr "type" "compare")])(define_insn "*sub_f_add_imm"[(set (reg:CC CC_REGNUM)(compare:CC (match_operand:SI 1 "gpr_operand" "r")(match_operand:SI 2 "arith_int_operand" "L")))(set (match_operand:SI 0 "gpr_operand" "=r")(plus:SI (match_dup 1) (match_operand:SI 3 "const_int_operand" "L")))]"INTVAL (operands[2]) == -INTVAL (operands[3])""sub %0,%1,%2"[(set_attr "type" "compare")])(define_expand "abssi2"[(set (match_dup 2) (const_int 0))(parallel [(set (reg:CC CC_REGNUM)(compare:CC (match_dup 2)(match_operand:SI 1 "nonmemory_operand" "")))(set (match_dup 3)(minus:SI (match_dup 2) (match_dup 1)))])(set (match_operand:SI 0 "gpr_operand" "=r")(if_then_else:SI (gt:SI (reg:CC CC_REGNUM) (const_int 0))(match_dup 3)(match_dup 1)))]"TARGET_CMOVE""operands[2] = gen_reg_rtx (SImode); operands[3] = gen_reg_rtx (SImode);")(define_insn "*add_c"[(set (reg:CC_C_LTU CC_REGNUM)(compare:CC_C_LTU(plus:SI (match_operand:SI 1 "gpr_operand" "%r,r")(match_operand:SI 2 "arith_operand" "r,L"))(match_dup 1)))(set (match_operand:SI 0 "gpr_operand" "=r,r")(plus:SI (match_dup 1) (match_dup 2)))]"""add %0,%1,%2"[(set_attr "type" "compare")])(define_insn "*add_c_rev"[(set (reg:CC_C_LTU CC_REGNUM)(compare:CC_C_LTU(plus:SI (match_operand:SI 1 "gpr_operand" "%r,r")(match_operand:SI 2 "arith_operand" "r,L"))(match_dup 1)))(set (match_operand:SI 0 "gpr_operand" "=r,r")(plus:SI (match_dup 2) (match_dup 1)))]"""add %0,%1,%2"[(set_attr "type" "compare")])(define_insn "*sub_c"[(set (reg:CC_C_GTU CC_REGNUM)(compare:CC_C_GTU(minus:SI (match_operand:SI 1 "gpr_operand" "r,r")(match_operand:SI 2 "arith_operand" "r,L"))(match_dup 1)))(set (match_operand:SI 0 "gpr_operand" "=r,r")(minus:SI (match_dup 1) (match_dup 2)))]"""sub %0,%1,%2"[(set_attr "type" "compare")])(define_insn "*sub_c_void"[(set (reg:CC_C_GTU CC_REGNUM)(compare:CC_C_GTU(minus:SI (match_operand:SI 1 "gpr_operand" "r,r")(match_operand:SI 2 "arith_operand" "r,L"))(match_dup 1)))(clobber (match_scratch:SI 0 "=r,r"))]"""sub %0,%1,%2"[(set_attr "type" "compare")]); floating point comparisons(define_insn "*cmpsf_cc_insn"[(match_parallel 3 "float_operation"[(set (reg:CC_FP CCFP_REGNUM)(compare:CC_FP (match_operand:SF 0 "gpr_operand" "r")(match_operand:SF 1 "gpr_operand" "r")))(clobber (match_scratch:SF 2 "=r"))])]"!TARGET_SOFT_CMPSF""fsub %2,%0,%1"[(set_attr "type" "fp")(set_attr "fp_mode" "round_unknown")]);; ??? do we have to relax the operand0 predicate to immediate_operand;; to allow the rtl loop optimizer to generate comparisons? OTOH;; we want call_address_operand to enforce valid operands so that;; combine won't do silly things, allowing instruction scheduling to do;; a proper job.(define_insn "*cmpsf_eq"[(set (reg:CC_FP_EQ CC_REGNUM) (compare:CC_FP_EQ (reg:SF 0) (reg:SF 1)))(use (match_operand:SI 0 "call_address_operand" "Csy,r"))(clobber (reg:SI GPR_IP))(clobber (reg:SI GPR_LR))]"TARGET_SOFT_CMPSF""%f0"[(set_attr "type" "sfunc")])(define_insn "*cmpsf_gte"[(set (reg:CC_FP_GTE CC_REGNUM) (compare:CC_FP_GTE (reg:SF 0) (reg:SF 1)))(use (match_operand:SI 0 "call_address_operand" "Csy,r"))(clobber (reg:SI GPR_IP))(clobber (reg:SI GPR_LR))]"TARGET_SOFT_CMPSF""%f0"[(set_attr "type" "sfunc")])(define_insn "*cmpsf_ord"[(set (reg:CC_FP_ORD CC_REGNUM) (compare:CC_FP_ORD (reg:SF 0) (reg:SF 1)))(use (match_operand:SI 0 "call_address_operand" "Csy,r"))(clobber (reg:SI GPR_IP))(clobber (reg:SI GPR_16))(clobber (reg:SI GPR_LR))]"TARGET_SOFT_CMPSF""%f0"[(set_attr "type" "sfunc")])(define_insn "*cmpsf_uneq"[(set (reg:CC_FP_UNEQ CC_REGNUM) (compare:CC_FP_UNEQ (reg:SF 0) (reg:SF 1)))(use (match_operand:SI 0 "call_address_operand" "Csy,r"))(clobber (reg:SI GPR_IP))(clobber (reg:SI GPR_16))(clobber (reg:SI GPR_LR))]"TARGET_SOFT_CMPSF""%f0"[(set_attr "type" "sfunc")]);; conditional moves(define_expand "mov<mode>cc"[(set (match_operand:WMODE 0 "gpr_operand" "")(if_then_else:WMODE (match_operand 1 "comparison_operator" "")(match_operand:WMODE 2 "gpr_operand" "")(match_operand:WMODE 3 "gpr_operand" "")))]"TARGET_CMOVE"{rtx cmp_op0 = XEXP (operands[1], 0);rtx cmp_op1 = XEXP (operands[1], 1);enum machine_mode cmp_in_mode;enum rtx_code code = GET_CODE (operands[1]);cmp_in_mode = GET_MODE (cmp_op0);if (cmp_in_mode == VOIDmode)cmp_in_mode = GET_MODE (cmp_op1);if (cmp_in_mode == VOIDmode)cmp_in_mode = SImode;/* If the operands are a better match when reversed, swap them now.This allows combine to see the proper comparison codes. */if (rtx_equal_p (operands[0], operands[2])&& !rtx_equal_p (operands[0], operands[3])){rtx tmp = operands[2]; operands[2] = operands[3]; operands[3] = tmp;code = (FLOAT_MODE_P (GET_MODE (cmp_op0))? reverse_condition_maybe_unordered (code): reverse_condition (code));}if (proper_comparison_operator (operands[1], VOIDmode))operands[1] = gen_rtx_fmt_ee (code, cmp_in_mode, cmp_op0, cmp_op1);else{if (!currently_expanding_to_rtl){/* ??? It would seem safest to FAIL here, but that would defeatthe purpose of having an if-conversion pass; its logic currentlyassumes that the backend should be safe to insert condition codesetting instructions, as the same condition codes were presumablyset by the if-conversion input code. */}/* What mode to give as first operand to gen_compare_reg here isdebatable. VOIDmode would be minimalist; telling gen_compare_regto use the mode of CC_REGNUM (or putting it on the comparisonoperator afterwards) is also a logical choice. OTOH, by using<MODE>mode, we have mode combine opportunities with flag settingoperations - if we get some. */operands[1]= gen_compare_reg (<MODE>mode, code, cmp_in_mode, cmp_op0, cmp_op1);}})(define_insn "*mov<mode>cc_insn"[(set (match_operand:WMODE 0 "gpr_operand" "=r")(if_then_else:WMODE (match_operator 3 "proper_comparison_operator"[(match_operand 4 "cc_operand") (const_int 0)])(match_operand:WMODE 1 "gpr_operand" "r")(match_operand:WMODE 2 "gpr_operand" "0")))]"TARGET_CMOVE""mov%d3 %0,%1"[(set_attr "type" "cmove")])(define_peephole2[(parallel [(set (match_operand:WMODE 0 "gpr_operand" "")(match_operand:WMODE 1 "" ""))(clobber (match_operand 8 "cc_operand"))])(match_operand 2 "" "")(set (match_operand:WMODE2 3 "gpr_operand" "")(match_operand:WMODE2 9 "gpr_operand" ""))(set (match_dup 3)(if_then_else:WMODE2 (match_operator 5 "proper_comparison_operator"[(match_operand 6 "cc_operand")(match_operand 7 "const0_operand")])(match_operand:WMODE2 4 "nonmemory_operand" "")(match_dup 3)))]"REGNO (operands[0]) == REGNO (operands[9])&& peep2_reg_dead_p (3, operands[0])&& !reg_set_p (operands[0], operands[2])&& !reg_set_p (operands[3], operands[2])&& !reg_overlap_mentioned_p (operands[3], operands[2])"[(parallel [(set (match_dup 10) (match_dup 1))(clobber (match_dup 8))])(match_dup 2)(set (match_dup 3)(if_then_else:WMODE2 (match_dup 5) (match_dup 4) (match_dup 3)))]{operands[10] = simplify_gen_subreg (<WMODE:MODE>mode, operands[3],<WMODE2:MODE>mode, 0);replace_rtx (operands[2], operands[9], operands[3]);replace_rtx (operands[2], operands[0], operands[10]);gcc_assert (!reg_overlap_mentioned_p (operands[0], operands[2]));})(define_peephole2[(parallel [(set (match_operand 6 "cc_operand") (match_operand 2 "" ""))(set (match_operand:WMODE 0 "gpr_operand" "")(match_operand:WMODE 1 "" ""))])(set (match_operand:WMODE2 3 "gpr_operand" "")(match_operand:WMODE2 4 "gpr_operand"))(set (match_dup 3)(if_then_else:WMODE2 (match_operator 5 "proper_comparison_operator"[(match_dup 6)(match_operand:WMODE 7 "const0_operand")])(match_operand:WMODE2 8 "gpr_operand")(match_dup 3)))]"REGNO (operands[0]) == REGNO (operands[8])&& REVERSIBLE_CC_MODE (GET_MODE (operands[6]))&& peep2_reg_dead_p (3, operands[6])&& peep2_reg_dead_p (3, operands[0])&& !reg_overlap_mentioned_p (operands[4], operands[3])"[(parallel [(set (match_dup 6) (match_dup 2))(set (match_dup 9) (match_dup 1))])(set (match_dup 3)(if_then_else:WMODE2 (match_dup 5) (match_dup 4) (match_dup 3)))]"{operands[5]= gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[5]),GET_MODE (operands[6])),GET_MODE (operands[5]), operands[6], operands[7]);operands[9] = simplify_gen_subreg (<WMODE:MODE>mode, operands[3],<WMODE2:MODE>mode, 0);}");; These control RTL generation for conditional jump insns;; To signal to can_compare_p that the cbranchs?4 patterns work,;; they must allow const0_rtx for both comparison operands(define_expand "cbranchsi4"[(set (reg CC_REGNUM)(compare (match_operand:SI 1 "add_operand" "")(match_operand:SI 2 "arith_operand" "")))(set (pc)(if_then_else(match_operator 0 "ordered_comparison_operator" [(reg CC_REGNUM)(const_int 0)])(label_ref (match_operand 3 "" ""))(pc)))]""{rtx cmp = gen_compare_reg (VOIDmode, GET_CODE (operands[0]), SImode,operands[1], operands[2]);emit_jump_insn (gen_branch_insn (operands[3], cmp, XEXP (cmp, 0)));DONE;})(define_expand "cbranchsf4"[(set (reg CC_REGNUM)(compare (match_operand:SF 1 "arith_operand" "")(match_operand:SF 2 "arith_operand" "")))(set (pc)(if_then_else(match_operator 0 "comparison_operator" [(reg CC_REGNUM)(const_int 0)])(label_ref (match_operand 3 "" ""))(pc)))]""{rtx cmp = gen_compare_reg (VOIDmode, GET_CODE (operands[0]), SFmode,operands[1], operands[2]);emit_jump_insn (gen_branch_insn (operands[3], cmp, XEXP (cmp, 0)));DONE;});; Now match both normal and inverted jump.(define_insn "branch_insn"[(set (pc)(if_then_else (match_operator 1 "proper_comparison_operator"[(match_operand 2 "cc_operand")(const_int 0)])(label_ref (match_operand 0 "" ""))(pc)))]"""b%d1 %l0"[(set_attr "type" "branch")])(define_insn "*rev_branch_insn"[(set (pc)(if_then_else (match_operator 1 "proper_comparison_operator"[(reg CC_REGNUM) (const_int 0)])(pc)(label_ref (match_operand 0 "" ""))))]"""b%D1 %l0"[(set_attr "type" "branch")]);; Unconditional and other jump instructions.(define_insn "jump"[(set (pc) (label_ref (match_operand 0 "" "")))]"""b %l0"[(set_attr "type" "uncond_branch")])(define_insn "indirect_jump"[(set (pc) (match_operand:SI 0 "gpr_operand" "r"))]"""jr %0"[(set_attr "type" "uncond_branch")])(define_expand "tablejump"[(parallel [(set (pc) (match_operand:SI 0 "gpr_operand" ""))(use (label_ref (match_operand 1 "" "")))])]""{/* In PIC mode, the table entries are stored PC relative.Convert the relative address to an absolute address. */if (flag_pic){rtx op1 = gen_rtx_LABEL_REF (Pmode, operands[1]);operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],op1, NULL_RTX, 0, OPTAB_DIRECT);}})(define_insn "*tablejump_internal"[(set (pc) (match_operand:SI 0 "gpr_operand" "r"))(use (label_ref (match_operand 1 "" "")))]"""jr %0;"[(set_attr "type" "uncond_branch")])(define_insn "*tablejump_hi_internal"[(set (pc) (match_operand:HI 0 "gpr_operand" "r"))(use (label_ref (match_operand 1 "" "")))]"optimize_size && TARGET_SMALL16""jr %0;"[(set_attr "type" "uncond_branch")])(define_expand "call";; operands[1] is stack_size_rtx;; operands[2] is next_arg_register[(parallel [(call (match_operand:SI 0 "call_operand" "")(match_operand 1 "" ""))(clobber (reg:SI GPR_LR))])]""{bool target_uninterruptible = epiphany_call_uninterruptible_p (operands[0]);if (!call_operand (operands[1], VOIDmode))operands[0]= change_address (operands[0], VOIDmode,copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));if (epiphany_uninterruptible_p (current_function_decl)!= target_uninterruptible){emit_insn (target_uninterruptible ? gen_gid (): gen_gie ());emit_call_insn(gen_rtx_PARALLEL(VOIDmode,gen_rtvec (2, gen_rtx_CALL (VOIDmode, operands[0], operands[1]),gen_rtx_CLOBBER (VOIDmode,gen_rtx_REG (SImode, GPR_LR)))));emit_insn (target_uninterruptible ? gen_gie (): gen_gid ());DONE;}})(define_insn "*call_i"[(match_parallel 2 "float_operation"[(call (mem:SI (match_operand:SI 0 "call_address_operand" "Csy,r"))(match_operand 1 "" ""))(clobber (reg:SI GPR_LR))])]"""%f0"[(set_attr "type" "call")])(define_expand "sibcall";; operands[1] is stack_size_rtx;; operands[2] is next_arg_register[(parallel [(call (match_operand:SI 0 "call_operand" "")(match_operand 1 "" ""))(return)])]""{bool target_uninterruptible = epiphany_call_uninterruptible_p (operands[0]);if (!call_operand (operands[1], VOIDmode))operands[0]= change_address (operands[0], VOIDmode,copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));if (epiphany_uninterruptible_p (current_function_decl)!= target_uninterruptible){emit_insn (target_uninterruptible ? gen_gid (): gen_gie ());emit_call_insn(gen_rtx_PARALLEL(VOIDmode,gen_rtvec (2, gen_rtx_CALL (VOIDmode, operands[0], operands[1]),ret_rtx)));emit_insn (target_uninterruptible ? gen_gie (): gen_gid ());DONE;}})(define_insn "*sibcall_i"[(call (mem:SI (match_operand:SI 0 "call_address_operand" "Csy,Rsc"))(match_operand 1 "" ""))(return)]"""@b %0jr %0"[(set_attr "type" "call")])(define_expand "call_value";; operand 2 is stack_size_rtx;; operand 3 is next_arg_register[(parallel [(set (match_operand 0 "gpr_operand" "=r")(call (match_operand:SI 1 "call_operand" "")(match_operand 2 "" "")))(clobber (reg:SI GPR_LR))])]""{bool target_uninterruptible = epiphany_call_uninterruptible_p (operands[1]);if (!call_operand (operands[1], VOIDmode))operands[1]= change_address (operands[1], VOIDmode,copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));if (epiphany_uninterruptible_p (current_function_decl)!= target_uninterruptible){emit_insn (target_uninterruptible ? gen_gid (): gen_gie ());emit_call_insn(gen_rtx_PARALLEL(VOIDmode,gen_rtvec (2, gen_rtx_SET(VOIDmode, operands[0],gen_rtx_CALL (VOIDmode, operands[1], operands[2])),gen_rtx_CLOBBER (VOIDmode,gen_rtx_REG (SImode, GPR_LR)))));emit_insn (target_uninterruptible ? gen_gie (): gen_gid ());DONE;}})(define_insn "*call_value_i"[(match_parallel 3 "float_operation"[(set (match_operand 0 "gpr_operand" "=r,r")(call (mem:SI (match_operand:SI 1 "call_address_operand" "Csy,r"))(match_operand 2 "" "")))(clobber (reg:SI GPR_LR))])]"""%f1"[(set_attr "type" "call")(set_attr "length" "4")])(define_expand "sibcall_value";; operand 2 is stack_size_rtx;; operand 3 is next_arg_register[(parallel [(set (match_operand 0 "gpr_operand" "=r")(call (match_operand:SI 1 "call_operand" "")(match_operand 2 "" "")))(return)])]""{bool target_uninterruptible = epiphany_call_uninterruptible_p (operands[1]);if (!call_operand (operands[1], VOIDmode))operands[1]= change_address (operands[1], VOIDmode,copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));if (epiphany_uninterruptible_p (current_function_decl)!= target_uninterruptible){emit_insn (target_uninterruptible ? gen_gid (): gen_gie ());emit_call_insn(gen_rtx_PARALLEL(VOIDmode,gen_rtvec (2, gen_rtx_SET(VOIDmode, operands[0],gen_rtx_CALL (VOIDmode, operands[1], operands[2])),ret_rtx)));emit_insn (target_uninterruptible ? gen_gie (): gen_gid ());DONE;}})(define_insn "*sibcall_value_i"[(set (match_operand 0 "gpr_operand" "=r,r")(call (mem:SI (match_operand:SI 1 "call_address_operand" "Csy,Rsc"))(match_operand 2 "" "")))(return)]"""@b %1jr %1"[(set_attr "type" "call")(set_attr "length" "4")])(define_expand "prologue"[(pc)]""{epiphany_expand_prologue ();DONE;})(define_expand "epilogue"[(pc)]""{epiphany_expand_epilogue (0);DONE;})(define_expand "sibcall_epilogue"[(pc)]""{epiphany_expand_epilogue (1);DONE;}); Since the demise of REG_N_SETS, it is no longer possible to find out; in the prologue / epilogue expanders how many times lr is set.; Using df_regs_ever_live_p to decide if lr needs saving means that; any explicit use of lr will cause it to be saved; hence we cannot; represent the blink use in return / sibcall instructions themselves, and; instead have to show it in EPILOGUE_USES.(define_insn "return_i"[(return)]"reload_completed""rts"[(set_attr "type" "uncond_branch")])(define_insn "return_internal_interrupt"[(return)(unspec_volatile [(const_int 0)] 1)]"""rti"[(set_attr "type" "uncond_branch")])(define_insn "stack_adjust_add"[(set (reg:SI GPR_SP)(plus:SI (reg:SI GPR_SP) (match_operand:SI 0 "arith_operand" "rL")))(clobber (reg:CC CC_REGNUM))(clobber (reg:SI STATUS_REGNUM))(clobber (match_operand:BLK 1 "memory_operand" "=m"))]"reload_completed""add sp,sp,%0")(define_insn "stack_adjust_mov"[(set (reg:SI GPR_SP) (reg:SI GPR_FP))(clobber (match_operand:BLK 0 "memory_operand" "=m"))]"reload_completed""mov sp,fp"[(set_attr "type" "move")])(define_insn "stack_adjust_str"[(set (match_operand 0 "stacktop_operand" "=m")(match_operand 1 "any_gpr_operand" "r"))(set (reg:SI GPR_SP)(plus:SI (reg:SI GPR_SP) (match_operand:SI 2 "nonmemory_operand" "rn")))(clobber (match_operand:BLK 3 "memory_operand" "=m"))]"reload_completed"{return (GET_MODE_SIZE (GET_MODE (operands[0])) <= 4? \"str %1,%0,%C2\" : \"strd %1,%0,%X2\");}[(set_attr "type" "store")])(define_insn "stack_adjust_ldr"[(set (match_operand:SI 0 "gpr_operand" "=r")(match_operand:SI 1 "stacktop_operand" "m"))(set (reg:SI GPR_SP)(plus:SI (reg:SI GPR_SP) (match_operand:SI 2 "nonmemory_operand" "rn")))(clobber (match_operand:BLK 3 "memory_operand" "=m"))]"reload_completed""ldr %0,%1,%C2"[(set_attr "type" "load")]);; Define some fake vector operations so that the vectorizer is happy to use;; 64 bit loads/stores.(define_expand "vec_unpacks_lo_v4hi"[(match_operand:V2SI 0 "gpr_operand")(match_operand:V4HI 1 "gpr_operand")]""{rtx in = simplify_gen_subreg (SImode, operands[1], V4HImode, 0);rtx outl = simplify_gen_subreg (SImode, operands[0], V2SImode, 0);rtx outh= simplify_gen_subreg (SImode, operands[0], V2SImode, UNITS_PER_WORD);if (reg_overlap_mentioned_p (outl, in))in = copy_to_mode_reg (SImode, in);emit_insn (gen_ashlsi3 (outl, in, GEN_INT (16)));emit_insn (gen_ashrsi3 (outl, outl, GEN_INT (16)));emit_insn (gen_ashrsi3 (outh, in, GEN_INT (16)));DONE;})(define_expand "vec_unpacks_hi_v4hi"[(match_operand:V2SI 0 "gpr_operand")(match_operand:V4HI 1 "gpr_operand")]""{rtx in = simplify_gen_subreg (SImode, operands[1], V4HImode, UNITS_PER_WORD);rtx outl = simplify_gen_subreg (SImode, operands[0], V2SImode, 0);rtx outh= simplify_gen_subreg (SImode, operands[0], V2SImode, UNITS_PER_WORD);if (reg_overlap_mentioned_p (outl, in))in = copy_to_mode_reg (SImode, in);emit_insn (gen_ashlsi3 (outl, in, GEN_INT (16)));emit_insn (gen_ashrsi3 (outl, outl, GEN_INT (16)));emit_insn (gen_ashrsi3 (outh, in, GEN_INT (16)));DONE;})(define_code_iterator addsub [plus minus])(define_code_iterator alu_binop[plus minus and ior xor])(define_code_attr insn_opname[(plus "add") (minus "sub") (mult "mul") (div "div")(and "and") (ior "ior") (xor "xor")]); You might think that this would work better as a define_expand, but; again lower_subreg pessimizes the code if it sees indiviudual operations.; We need to keep inputs and outputs as register pairs if we want to; get sensible register allocation for double-word load and store operations.(define_insn_and_split "<insn_opname>v2si3"[(set (match_operand:V2SI 0 "gpr_operand" "=r")(alu_binop:V2SI (match_operand:V2SI 1 "gpr_operand" "r")(match_operand:V2SI 2 "gpr_operand" "r")))(clobber (reg:CC CC_REGNUM))]"""#""reload_completed || (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)"[(const_int 0)]{rtx o0l, o0h, o1l, o1h, o2l, o2h;o0l = simplify_gen_subreg (SImode, operands[0], V2SImode, 0);o0h = simplify_gen_subreg (SImode, operands[0], V2SImode, UNITS_PER_WORD);o1l = simplify_gen_subreg (SImode, operands[1], V2SImode, 0);o1h = simplify_gen_subreg (SImode, operands[1], V2SImode, UNITS_PER_WORD);o2l = simplify_gen_subreg (SImode, operands[2], V2SImode, 0);o2h = simplify_gen_subreg (SImode, operands[2], V2SImode, UNITS_PER_WORD);if (reg_overlap_mentioned_p (o0l, o1h))o1h = copy_to_mode_reg (SImode, o1h);if (reg_overlap_mentioned_p (o0l, o2h))o2h = copy_to_mode_reg (SImode, o2h);emit_insn (gen_<insn_opname>si3 (o0l, o1l, o2l));emit_insn (gen_<insn_opname>si3 (o0h, o1h, o2h));DONE;}[(set_attr "length" "8")])(define_expand "<insn_opname>v2sf3"[(parallel[(set (match_operand:V2SF 0 "gpr_operand" "")(addsub:V2SF (match_operand:V2SF 1 "gpr_operand" "")(match_operand:V2SF 2 "gpr_operand" "")))(clobber (reg:CC_FP CCFP_REGNUM))])])(define_insn_and_split "<insn_opname>v2sf3_i"[(match_parallel 3 "float_operation"[(set (match_operand:V2SF 0 "gpr_operand" "=r")(addsub:V2SF (match_operand:V2SF 1 "gpr_operand" "r")(match_operand:V2SF 2 "gpr_operand" "r")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""#""reload_completed || (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)"[(parallel[(set (match_dup 4) (addsub:SF (match_dup 5) (match_dup 6)))(clobber (reg:CC_FP CCFP_REGNUM))(match_dup 10)(match_dup 11)])(parallel[(set (match_dup 7) (addsub:SF (match_dup 8) (match_dup 9)))(clobber (reg:CC_FP CCFP_REGNUM))(match_dup 10)(match_dup 11)])]{operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);operands[5] = simplify_gen_subreg (SFmode, operands[1], V2SFmode, 0);operands[6] = simplify_gen_subreg (SFmode, operands[2], V2SFmode, 0);operands[7]= simplify_gen_subreg (SFmode, operands[0], V2SFmode, UNITS_PER_WORD);operands[8]= simplify_gen_subreg (SFmode, operands[1], V2SFmode, UNITS_PER_WORD);operands[9]= simplify_gen_subreg (SFmode, operands[2], V2SFmode, UNITS_PER_WORD);if (!reload_completed){if (reg_overlap_mentioned_p (operands[4], operands[8]))operands[8] = copy_to_mode_reg (SFmode, operands[8]);if (reg_overlap_mentioned_p (operands[4], operands[9]))operands[9] = copy_to_mode_reg (SFmode, operands[9]);emit_insn (gen_<insn_opname>sf3 (operands[4], operands[5], operands[6]));emit_insn (gen_<insn_opname>sf3 (operands[7], operands[8], operands[9]));DONE;}gcc_assert (!reg_overlap_mentioned_p (operands[4], operands[8]));gcc_assert (!reg_overlap_mentioned_p (operands[4], operands[9]));operands[10] = XVECEXP (operands[3], 0, XVECLEN (operands[3], 0) - 2);operands[11] = XVECEXP (operands[3], 0, XVECLEN (operands[3], 0) - 1);}[(set_attr "length" "8")(set_attr "type" "fp")])(define_expand "mul<mode>3"[(parallel[(set (match_operand:DWV2MODE 0 "gpr_operand" "")(mult:DWV2MODE (match_operand:DWV2MODE 1 "gpr_operand" "")(match_operand:DWV2MODE 2 "gpr_operand" "")))(clobber (reg:CC_FP CCFP_REGNUM))])])(define_insn_and_split "mul<mode>3_i"[(match_parallel 3 "float_operation"[(set (match_operand:DWV2MODE 0 "gpr_operand" "=r")(mult:DWV2MODE (match_operand:DWV2MODE 1 "gpr_operand" "r")(match_operand:DWV2MODE 2 "gpr_operand" "r")))(clobber (reg:CC_FP CCFP_REGNUM))])]"""#""reload_completed || (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)"[(parallel[(set (match_dup 4) (mult:<vmode_PART> (match_dup 5) (match_dup 6)))(clobber (reg:CC_FP CCFP_REGNUM))(match_dup 10)(match_dup 11)])(parallel[(set (match_dup 7) (mult:<vmode_PART> (match_dup 8) (match_dup 9)))(clobber (reg:CC_FP CCFP_REGNUM))(match_dup 10)(match_dup 11)])]{operands[4]= simplify_gen_subreg (<vmode_PART>mode, operands[0], <MODE>mode, 0);operands[5]= simplify_gen_subreg (<vmode_PART>mode, operands[1], <MODE>mode, 0);operands[6]= simplify_gen_subreg (<vmode_PART>mode, operands[2], <MODE>mode, 0);operands[7] = simplify_gen_subreg (<vmode_PART>mode, operands[0],<MODE>mode, UNITS_PER_WORD);operands[8] = simplify_gen_subreg (<vmode_PART>mode, operands[1],<MODE>mode, UNITS_PER_WORD);operands[9] = simplify_gen_subreg (<vmode_PART>mode, operands[2],<MODE>mode, UNITS_PER_WORD);if (!reload_completed){if (reg_overlap_mentioned_p (operands[4], operands[8]))operands[8] = copy_to_mode_reg (<vmode_PART>mode, operands[8]);if (reg_overlap_mentioned_p (operands[4], operands[9]))operands[9] = copy_to_mode_reg (<vmode_PART>mode, operands[9]);emit_insn (gen_mul<vmode_part>3 (operands[4], operands[5], operands[6]));emit_insn (gen_mul<vmode_part>3 (operands[7], operands[8], operands[9]));DONE;}gcc_assert (!reg_overlap_mentioned_p (operands[4], operands[8]));gcc_assert (!reg_overlap_mentioned_p (operands[4], operands[9]));operands[10] = XVECEXP (operands[3], 0, XVECLEN (operands[3], 0) - 2);operands[11] = XVECEXP (operands[3], 0, XVECLEN (operands[3], 0) - 1);}[(set_attr "length" "8")(set_attr "type" "<vmode_fp_type>")])(define_insn_and_split "*fmadd<mode>_combine"[(match_parallel 4 "float_operation"[(set (match_operand:DWV2MODE 0 "gpr_operand" "=r")(plus:DWV2MODE (mult:<MODE>(match_operand:<MODE> 1 "gpr_operand" "r")(match_operand:<MODE> 2 "gpr_operand" "r"))(match_operand:<MODE> 3 "gpr_operand" "0")))(clobber (reg:CC_FP CCFP_REGNUM))])]"TARGET_FUSED_MADD || <MODE>mode == V2SImode""#""reload_completed || (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)"[(parallel[(set (match_dup 5)(plus:<vmode_PART> (mult:<vmode_PART> (match_dup 6) (match_dup 7))(match_dup 8)))(clobber (reg:CC_FP CCFP_REGNUM))(match_dup 13)(match_dup 14)])(parallel[(set (match_dup 9)(plus:<vmode_PART> (mult:<vmode_PART> (match_dup 10) (match_dup 11))(match_dup 12)))(clobber (reg:CC_FP CCFP_REGNUM))(match_dup 13)(match_dup 14)])]{operands[5]= simplify_gen_subreg (<vmode_PART>mode, operands[0], <MODE>mode, 0);operands[6]= simplify_gen_subreg (<vmode_PART>mode, operands[1], <MODE>mode, 0);operands[7]= simplify_gen_subreg (<vmode_PART>mode, operands[2], <MODE>mode, 0);operands[8]= simplify_gen_subreg (<vmode_PART>mode, operands[3], <MODE>mode, 0);operands[9] = simplify_gen_subreg (<vmode_PART>mode, operands[0],<MODE>mode, UNITS_PER_WORD);operands[10] = simplify_gen_subreg (<vmode_PART>mode, operands[1],<MODE>mode, UNITS_PER_WORD);operands[11] = simplify_gen_subreg (<vmode_PART>mode, operands[2],<MODE>mode, UNITS_PER_WORD);operands[12] = simplify_gen_subreg (<vmode_PART>mode, operands[3],<MODE>mode, UNITS_PER_WORD);if (!reload_completed){if (reg_overlap_mentioned_p (operands[5], operands[10]))operands[10] = copy_to_mode_reg (<vmode_PART>mode, operands[10]);if (reg_overlap_mentioned_p (operands[5], operands[11]))operands[11] = copy_to_mode_reg (<vmode_PART>mode, operands[11]);if (reg_overlap_mentioned_p (operands[5], operands[12]))operands[12] = copy_to_mode_reg (<vmode_PART>mode, operands[12]);emit_insn (gen_madd<vmode_part> (operands[5], operands[6], operands[7],operands[8]));emit_insn (gen_madd<vmode_part> (operands[9], operands[10], operands[11],operands[12]));DONE;}gcc_assert (!reg_overlap_mentioned_p (operands[5], operands[10]));gcc_assert (!reg_overlap_mentioned_p (operands[5], operands[11]));gcc_assert (!reg_overlap_mentioned_p (operands[5], operands[12]));operands[13] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);operands[14] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);}[(set_attr "length" "8")(set_attr "type" "<vmode_fp_type>")])(define_expand "vec_set<mode>"[(match_operand:DWV2MODE 0 "register_operand")(match_operand:<vmode_PART> 1 "register_operand")(match_operand 2 "const_int_operand" "")]""{operands[0]= simplify_gen_subreg (<vmode_PART>mode, operands[0], <MODE>mode,UNITS_PER_WORD * INTVAL (operands[2]));emit_move_insn (operands[0], operands[1]);DONE;})(define_insn "nop"[(const_int 0)]"""nop"[(set_attr "type" "flow")])
