\\ Addition Instructions \\ Creating abstract patterns for addition instructions. abstract set_plus extends set { root.2 := plus; } abstract sequence_set_plus extends sequence { root.1 := set_plus; root.2 := set_plus; } abstract signext_plus extends sign_extend { root.1 := plus; } abstract set_signext_plus extends set { root.2 := signext_plus; } abstract parallel_set_clobber extends parallel { root.1 := set; root.2 := clobber; } abstract scratch_set_set_clobber extends sequence { root.2 := set; root.4 := parallel_set_clobber; } abstract parallel_clobber_set extends sequence { root.1 := parallel_set_clobber; root.2 := set; } abstract subreg_plus extends subreg { root.1 := plus; } abstract zext_subreg_plus extends set { root.2 := zero_extend; root.2.1 := subreg_plus; } abstract truncate_plus extends truncate { root.1 := plus; } abstract zext_truncate_plus extends set { root.2 := zero_extend; root.2.1 := truncate_plus; } \\ **************** Concrete Patterns****************** concrete add3.insn instantiates set_plus { set_plus(register_operand:ANYF:"=f", register_operand:ANYF:"f", register_operand:ANYF:"f"); root.2.mode := ANYF; } {: "" "add.\t%0,%1,%2" [(set_attr "type" "fadd") (set_attr "mode" "")]) :} concrete add3.expand instantiates set_plus { set_plus(register_operand:GPR:"", register_operand:GPR:"", arith_operand:GPR:""); root.2.mode := GPR; } {: "" :} concrete *add3.insn overrides add3.expand { allconstraints:= ("=d,d","d,d", "d,Q"); } {: "!TARGET_MIPS16" "@ addu\t%0,%1,%2 addiu\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "")]) :} concrete *add3_mips16.insn overrides add3.expand { allconstraints := ("=ks,d,d,d,d", "ks,ks,0,d,d", "Q,Q,Q,0,d"); } {: "TARGET_MIPS16" "@ addiu\t%0,%2 addiu\t%0,%1,%2 addiu\t%0,%2 addiu\t%0,%1,%2 addu\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "") (set_attr_alternative "length" [(if_then_else (match_operand 2 "m16_simm8_8") (const_int 4) (const_int 8)) (if_then_else (match_operand 2 "m16_uimm_4") (const_int 4) (const_int 8)) (if_then_else (match_operand 2 "m16_simm_1") (const_int 4) (const_int 8)) (if_then_else (match_operand 2 "m16_simm4_1") (const_int 4) (const_int 8)) (const_int 4)])]) :} \\ On the mips16, we can sometimes split an add of a constant which is \\ a 4 byte instruction into two adds which are both 2 byte \\ instructions. There are two cases: one where we are adding a \\ constant plus a register to another register, and one where we are \\ simply adding a constant to a register. concrete .split instantiates.in set_plus { set_plus(d_operand:SI:"", duplicate 0, const_int_operand:SI:""); root.2.mode := SI; } cmd_spec.in {: "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && ((INTVAL (operands[1]) > 0x7f && INTVAL (operands[1]) <= 0x7f + 0x7f) || (INTVAL (operands[1]) < - 0x80 && INTVAL (operands[1]) >= - 0x80 - 0x80))" :} instantiates.out set_plus { set_plus(duplicate 0, duplicate 0, duplicate 1); root.2.mode := SI; } instantiates.out set_plus { set_plus( duplicate 0, duplicate 0, duplicate 2); root.2.mode := SI; } cmd_spec.out {: { HOST_WIDE_INT val = INTVAL (operands[1]); if (val >= 0) { operands[1] = GEN_INT (0x7f); operands[2] = GEN_INT (val - 0x7f); } else { operands[1] = GEN_INT (- 0x80); operands[2] = GEN_INT (val + 0x80); } } :} concrete .split instantiates.in set_plus { set_plus(d_operand:SI:"", d_operand:SI:"", const_int_operand:SI:""); root.2.mode := SI; } cmd_spec.in {: "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && REGNO (operands[0]) != REGNO (operands[1]) && ((INTVAL (operands[2]) > 0x7 && INTVAL (operands[2]) <= 0x7 + 0x7f) || (INTVAL (operands[2]) < - 0x8 && INTVAL (operands[2]) >= - 0x8 - 0x80))" :} instantiates.out set_plus { set_plus(duplicate 0, duplicate 1, duplicate 2); } instantiates.out set_plus { set_plus( duplicate 0, duplicate 0, duplicate 3); } cmd_spec.out {: { HOST_WIDE_INT val = INTVAL (operands[2]); if (val >= 0) { operands[2] = GEN_INT (0x7); operands[3] = GEN_INT (val - 0x7); } else { operands[2] = GEN_INT (- 0x8); operands[3] = GEN_INT (val + 0x8); } } :} concrete .split instantiates.in set_plus { set_plus(d_operand:DI:"", duplicate 0, const_int_operand:DI:""); root.2.mode := DI; } cmd_spec.in {: "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE && ((INTVAL (operands[1]) > 0xf && INTVAL (operands[1]) <= 0xf + 0xf) || (INTVAL (operands[1]) < - 0x10 && INTVAL (operands[1]) >= - 0x10 - 0x10))" :} instantiates.out set_plus { set_plus(duplicate 0, duplicate 0, duplicate 1); } instantiates.out set_plus { set_plus( duplicate 0, duplicate 0, duplicate 2); } cmd_spec.out {: { HOST_WIDE_INT val = INTVAL (operands[1]); if (val >= 0) { operands[1] = GEN_INT (0xf); operands[2] = GEN_INT (val - 0xf); } else { operands[1] = GEN_INT (- 0x10); operands[2] = GEN_INT (val + 0x10); } } :} concrete .split instantiates.in set_plus { set_plus(d_operand:DI:"",d_operand:DI:"",const_int_operand:DI:""); } cmd_spec.in {: "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE && REGNO (operands[0]) != REGNO (operands[1]) && ((INTVAL (operands[2]) > 0x7 && INTVAL (operands[2]) <= 0x7 + 0xf) || (INTVAL (operands[2]) < - 0x8 && INTVAL (operands[2]) >= - 0x8 - 0x10))" :} instantiates.out set_plus { set_plus(duplicate 0, duplicate 1, duplicate 2); } instantiates.out set_plus { set_plus( duplicate 0, duplicate 0, duplicate 3); } cmd_spec.out {: { HOST_WIDE_INT val = INTVAL (operands[2]); if (val >= 0) { operands[2] = GEN_INT (0x7); operands[3] = GEN_INT (val - 0x7); } else { operands[2] = GEN_INT (- 0x8); operands[3] = GEN_INT (val + 0x8); } } :} concrete *addsi3_extended.insn instantiates set_signext_plus { set_signext_plus(register_operand:DI:"=d,d", register_operand:SI:"d,d", arith_operand:SI:"d,Q"); root.2.mode := DI; root.2.1.mode := SI; } {: "TARGET_64BIT && !TARGET_MIPS16" "@ addu\t%0,%1,%2 addiu\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) :} concrete *addsi3_extended_mips16.insn_and_split overrides.in *addsi3_extended.insn { allconstraints := ("=d,d,d","=0,d,d","Q,O,d"); } cmd_spec.in {: "TARGET_64BIT && TARGET_MIPS16" "#" "&& reload_completed" :} instantiates.out set_plus { set_plus(duplicate 3, duplicate 1, duplicate 2); root.2.mode := SI; } cmd_spec.out {: { operands[3] = gen_lowpart (SImode, operands[0]); } [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "extended_mips16" "yes")]) :} concrete *baddu_si_eb.insn instantiates zext_subreg_plus { zext_subreg_plus(register_operand:SI:"=d", register_operand:SI:"d", register_operand:SI:"d", 3); root.2.mode := SI; root.2.1.mode := QI; root.2.1.1.mode := SI; } {: "ISA_HAS_BADDU && BYTES_BIG_ENDIAN" "baddu\\t%0,%1,%2" [(set_attr "type" "arith")]) :} concrete *baddu_si_el.insn overrides *baddu_si_eb.insn { root.2.1.2 := 0; } {: "ISA_HAS_BADDU && !BYTES_BIG_ENDIAN" "baddu\\t%0,%1,%2" [(set_attr "type" "arith")]) :} concrete *baddu_di.insn instantiates zext_truncate_plus { zext_truncate_plus(register_operand:GPR:"=d", register_operand:DI:"d", register_operand:DI:"d"); root.2.mode := GPR; root.2.1.mode := QI; root.2.1.1.mode := DI; } {: "ISA_HAS_BADDU && TARGET_64BIT" "baddu\\t%0,%1,%2" [(set_attr "type" "arith")]) :} concrete .peephole2 cmd_spec.in {: [match_scratch:SI 0 "d"] :} instantiates.in set { set(lo_operand:SI:"", d_operand:SI:""); } cmd_spec.in {: [match_dup 0] :} instantiates.in parallel_set_clobber { parallel_set_clobber( d_operand:SI:"", macc_msac_operand:SI:"", duplicate 1); } instantiates.out parallel_set_clobber { parallel_set_clobber(duplicate 0, duplicate 5, duplicate 1); } instantiates.out set { set(duplicate 3, duplicate 6); }