; Internal TSTPORT instruction, used to generate a single TSTPORT
; instruction for use in the testport branch split.
(UNSPEC_INTERNAL_TESTPORT 19)
-
- ; instruction for use in the profile based optimizations.
- (UNSPEC_INTERNAL_PROFILE 20)
]
)
(define_insn_and_split "cbranchhi4"
[(set (pc)
(if_then_else
- (match_operator:CC 0 "comparison_operator"
+ (match_operator:CC 0 "ordered_comparison_operator"
[(match_operand:HI 1 "register_operand" "r")
(match_operand:HI 2 "picochip_comparison_operand" "ri")])
(label_ref (match_operand 3 "" ""))
(set_attr "length" "2,2,4")
])
+;; This pattern was added to match the previous pattern. When doing if-convert
+;; the pattern generated using movhicc does not have a eq:CC but only a eq for
+;; operator. If this pattern were not to be there, Gcc decides not to use
+;; movhicc at all. Whereas, in Gcc 4.4, it seems to be cleverer.
+(define_insn "*supported_compare1"
+ [(set (reg:CC CC_REGNUM)
+ (match_operator 0 "picochip_supported_comparison_operator"
+ [(match_operand:HI 1 "register_operand" "r,r,r")
+ (match_operand:HI 2 "picochip_comparison_operand" "r,J,i")]))]
+ ""
+ "* return picochip_output_compare(operands);"
+ [; Must be picoAlu because it sets the condition flags.
+ (set_attr "type" "picoAlu,picoAlu,picoAlu")
+ (set_attr "longConstant" "false,false,true")
+ (set_attr "length" "2,2,4")
+ ])
+
(define_insn "*compare"
[(set (reg:CC CC_REGNUM)
(match_operator:CC 0 "comparison_operator"
; Match a branch instruction, created from a tstport/cbranch split.
; We use a "use" clause so GCC doesnt try to use this pattern generally.
-(define_insn "*branch"
+(define_insn "branch"
[(set (pc)
(if_then_else
(match_operator 2 "comparison_operator"
rtx shiftVal;
rtx loadedValue;
rtx addressMask;
+ rtx topByteValue;
+ rtx signExtendedValue;
+
warn_of_byte_access();
emit_insn(gen_rtx_SET(HImode, loadedValue, gen_rtx_MEM(HImode, wordAddress)));
/* Shift the desired byte to the most significant byte. */
- rtx topByteValue = gen_reg_rtx (HImode);
+ topByteValue = gen_reg_rtx (HImode);
emit_insn (gen_ashlhi3 (topByteValue, loadedValue, shiftVal));
/* Sign extend the top-byte back into the bottom byte. */
- rtx signExtendedValue = gen_reg_rtx(HImode);
+ signExtendedValue = gen_reg_rtx(HImode);
emit_insn(gen_ashrhi3(signExtendedValue, topByteValue, GEN_INT(8)));
/* Final extraction of QI mode register. */
{
rtx zeroingByteMask;
rtx temp;
- rtx tempQiMode;
rtx tempHiMode;
+ rtx lsbByteMask;
/* Get the address. */
address = gen_reg_rtx(HImode);
* bits, instead of the original memory value which is being
* modified.
*/
- /*if (register_operand(operands[1],QImode))
- {
- tempHiMode = XEXP(operands[1], 0);
- }
- else
- {
- tempHiMode = operands[1];
- }*/
- //tempHiMode = force_reg(QImode, operands[1]);
tempHiMode = simplify_gen_subreg(HImode, operands[1], QImode, 0);
temp = gen_reg_rtx(HImode);
emit_insn(gen_rtx_SET(HImode, temp, tempHiMode));
- rtx lsbByteMask = gen_reg_rtx (HImode);
+ lsbByteMask = gen_reg_rtx (HImode);
emit_insn (gen_rtx_SET (HImode, lsbByteMask, GEN_INT (0xFF)));
emit_insn (gen_andhi3 (temp, temp, lsbByteMask));
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))]
- ""
+ "reload_completed"
[(set (match_dup 2) (match_dup 3))
(set (match_dup 4) (match_dup 5))]
"{
// %R0 := #%1 (SF)\n\tCOPY.%# %L1,%L0\n\tCOPY.%# %U1,%U0
STL %R1,%a0\t\t// Mem(%M0{byte}) :={SF} %R1")
+;; memcpy pattern
+;; 0 = destination (mem:BLK ...)
+;; 1 = source (mem:BLK ...)
+;; 2 = count
+;; 3 = alignment
+(define_expand "movmemhi"
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")
+ (match_operand:HI 2 "immediate_operand" "")
+ (match_operand 3 "" "")]
+ "picochip_schedule_type != DFA_TYPE_NONE"
+ "if (picochip_expand_movmemhi(operands)) DONE; FAIL;"
+)
+
;;===========================================================================
;; NOP
;;===========================================================================
{
/* Synthesise a variable shift. */
+ rtx tmp1;
+ rtx tmp2;
+ rtx tmp3;
+ rtx minus_one;
+ rtx tmp4;
+
/* Fill a temporary with the sign bits. */
- rtx tmp1 = gen_reg_rtx (HImode);
+ tmp1 = gen_reg_rtx (HImode);
emit_insn (gen_builtin_asri (tmp1, operands[1], GEN_INT(15)));
/* Shift the unsigned value. */
- rtx tmp2 = gen_reg_rtx (HImode);
+ tmp2 = gen_reg_rtx (HImode);
emit_insn (gen_lshrhi3 (tmp2, operands[1], operands[2]));
/* The word of sign bits must be shifted back to the left, to zero
* count). Since the shifts are computed modulo 16 (i.e., only the
* lower 4 bits of the count are used), the shift amount (15 - count)
* is equivalent to !count. */
- rtx tmp3 = gen_reg_rtx (HImode);
- rtx tmp3_1 = GEN_INT (-1);
- emit_insn (gen_xorhi3 (tmp3, operands[2], tmp3_1));
- rtx tmp4 = gen_reg_rtx (HImode);
+ tmp3 = gen_reg_rtx (HImode);
+ minus_one = GEN_INT (-1);
+ emit_insn (gen_xorhi3 (tmp3, operands[2], minus_one));
+ tmp4 = gen_reg_rtx (HImode);
emit_insn (gen_ashlhi3 (tmp4, tmp1, tmp3));
/* Combine the sign bits with the shifted value. */
[(set_attr "length" "1")
(set_attr "type" "unknown")])
-(define_insn "profile"
- [(unspec_volatile [(match_operand:HI 0 "const_int_operand" "i")]
- UNSPEC_INTERNAL_PROFILE)]
- ""
- "PROFILE_DUMMY %0 \t// (profile instruction %0)"
- [(set_attr "length" "1")
- (set_attr "type" "unknown")])
-
(define_insn "internal_testport"
[(set (reg:CC CC_REGNUM)
(unspec_volatile:CC [(match_operand:HI 0 "const_int_operand" "i")]
UNSPEC_TESTPORT))
(clobber (reg:CC CC_REGNUM))]
""
- "// %0 := TestPort(%1)\;TSTPORT %1\;COPYSW.0 %0\;AND.0 %0,8,%0"
+ "// %0 := TestPort(%1)\;COPY.1 0,%0 %| TSTPORT %1\;COPYEQ 1,%0"
[(set_attr "length" "9")])
; Entry point for array tstport (the actual port index is computed as the
;;============================================================================
;; Define expand seems to consider the resulting two instructions to be
-;; independent. It was moving the actual copy instruction further down
-;; with a call instruction in between. The call was clobbering the CC
-;; and hence the cond_copy was wrong. With a split, it works correctly.
+;; independent. With a split, guarded by reload, it works correctly.
(define_expand "movhicc"
- [(set (reg:CC CC_REGNUM) (match_operand 1 "comparison_operator" ""))
- (parallel [(set (match_operand:HI 0 "register_operand" "=r,r")
- (if_then_else:HI (match_op_dup:HI 1 [(reg:CC CC_REGNUM) (const_int 0)])
- (match_operand:HI 2 "picochip_register_or_immediate_operand" "0,0")
- (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i")))
- (use (match_dup 4))])]
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (if_then_else:HI (match_operand:HI 1 "" "")
+ (match_operand:HI 2 "register_operand" "0,0")
+ (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i")))]
""
{if (!picochip_check_conditional_copy (operands))
FAIL;
- operands[4] = GEN_INT(GET_CODE(operands[1]));
})
+(define_insn_and_split "*checked_movhicc"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (if_then_else:HI (match_operator 1 "picochip_peephole_comparison_operator"
+ [(match_operand:HI 4 "register_operand" "r,r")
+ (match_operand:HI 5 "picochip_comparison_operand" "r,i")])
+ (match_operand:HI 2 "register_operand" "0,0")
+ (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i")))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (reg:CC CC_REGNUM) (match_dup 1))
+ (parallel [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (if_then_else:HI (match_op_dup:HI 1 [(reg:CC CC_REGNUM) (const_int 0)])
+ (match_operand:HI 2 "picochip_register_or_immediate_operand" "0,0")
+ (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i")))
+ (use (match_dup 6))])]
+ "{
+ operands[6] = GEN_INT(GET_CODE(operands[0]));
+ }")
+
;; We dont do any checks here. But this pattern is used only when movhicc
;; was checked. Put a "use" clause to make sure.
(define_insn "*conditional_copy"
(if_then_else:HI
(match_operator:HI 4 "picochip_peephole_comparison_operator"
[(reg:CC CC_REGNUM) (const_int 0)])
- (match_operand:HI 1 "picochip_register_or_immediate_operand" "0,0")
+ (match_operand:HI 1 "register_operand" "0,0")
(match_operand:HI 2 "picochip_register_or_immediate_operand" "r,i")))
(use (match_operand:HI 3 "const_int_operand" ""))]
""
(set_attr "type" "picoAlu,picoAlu")
(set_attr "longConstant" "false,true")])
-;; cmphi - This needs to be defined, to ensure that the conditional
-;; move works properly (because the if-cvt code uses this pattern to
-;; build the conditional move, even though normally we use cbranch to
-;; directly generate the instructions).
-
-(define_expand "cmphi"
- [(match_operand:HI 0 "general_operand" "g")
- (match_operand:HI 1 "general_operand" "g")]
- ""
- "DONE;")
-
-;;============================================================================
-;; Branch patterns - needed for conditional moves. This is because
-;; they result in the bcc_gen_fctn array being initialised with the
-;; code to define_expand the following, and this in turn means that
-;; when noce_emit_cmove is called, the correct pattern can be
-;; generated, based upon the assumed presence of the following. The
-;; following are never actually used, because the earlier cbranch
-;; patterns take precendence.
-;;============================================================================
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else
- (ne (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "beq"
- [(set (pc)
- (if_then_else
- (eq (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else
- (lt (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else
- (ge (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else
- (geu (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else
- (ltu (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else
- (le (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else
- (gt (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else
- (leu (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else
- (gtu (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
;;============================================================================
;; Scheduling, including delay slot scheduling.
;;============================================================================
(const_string "unknown"))
(define_attr "schedType" "none,space,speed"
- (const (symbol_ref "picochip_schedule_type")))
+ (const (symbol_ref "(enum attr_schedType) picochip_schedule_type")))
;; Define whether an instruction uses a long constant.