Home | History | Annotate | Line # | Download | only in h8300
      1 ;; ----------------------------------------------------------------------
      2 ;; TEST INSTRUCTIONS
      3 ;; ----------------------------------------------------------------------
      4 
      5 ;; (define_insn_and_split "*tst_extzv_1_n"
      6 ;;   [(set (cc0)
      7 ;; 	(compare (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")
      8 ;; 				  (const_int 1)
      9 ;; 				  (match_operand 1 "const_int_operand" "n,n,n"))
     10 ;; 		 (const_int 0)))
     11 ;;   (clobber (match_scratch:QI 2 "=X,X,&r"))]
     12 ;;  "!CONSTANT_P (operands[0])"
     13 ;;  "@
     14 ;;   btst\\t%Z1,%Y0
     15 ;;   btst\\t%Z1,%Y0
     16 ;;   #"
     17 ;;  "&& reload_completed
     18 ;;   && !satisfies_constraint_U (operands[0])"
     19 ;;  [(set (match_dup 2)
     20 ;;	(match_dup 0))
     21 ;;   (parallel [(set (cc0) (compare (zero_extract:SI (match_dup 2)
     22 ;;						   (const_int 1)
     23 ;;						   (match_dup 1))
     24 ;;				  (const_int 0)))
     25 ;;	      (clobber (scratch:QI))])]
     26 ;;  ""
     27 ;;  [(set_attr "length" "2,8,10")])
     28 ;;
     29 (define_insn ""
     30   [(set (reg:CCZ CC_REG)
     31 	(eq (zero_extract:HSI (match_operand:HSI 0 "register_operand" "r")
     32 			      (const_int 1)
     33 			      (match_operand 1 "const_int_operand" "n"))
     34 	    (const_int 0)))]
     35   "INTVAL (operands[1]) < 16"
     36   "btst	%Z1,%Y0"
     37   [(set_attr "length" "2")])
     38 
     39 (define_insn "*tst<mode>"
     40   [(set (reg:CCZN CC_REG)
     41 	(compare:CCZN (match_operand:QHSI 0 "register_operand" "r")
     42 		      (const_int 0)))]
     43   ""
     44   {
     45     if (<MODE>mode == QImode)
     46       return "mov.b	%X0,%X0";
     47     else if (<MODE>mode == HImode)
     48       return "mov.w	%T0,%T0";
     49     else if (<MODE>mode == SImode)
     50       return "mov.l	%S0,%S0";
     51     gcc_unreachable ();
     52   }
     53   [(set_attr "length" "2")])
     54 
     55 (define_insn "*tsthi_upper"
     56   [(set (reg:CCZN CC_REG)
     57 	(compare (and:HI (match_operand:HI 0 "register_operand" "r")
     58 			 (const_int -256))
     59 		 (const_int 0)))]
     60   "reload_completed"
     61   "mov.b	%t0,%t0"
     62   [(set_attr "length" "2")])
     63 
     64 (define_insn "*tstsi_upper"
     65   [(set (reg:CCZN CC_REG)
     66 	(compare (and:SI (match_operand:SI 0 "register_operand" "r")
     67 			 (const_int -65536))
     68 		 (const_int 0)))]
     69   "reload_completed"
     70   "mov.w	%e0,%e0"
     71   [(set_attr "length" "2")])
     72 
     73 (define_insn "*cmp<mode>_c"
     74   [(set (reg:CCC CC_REG)
     75 	(ltu (match_operand:QHSI 0 "h8300_dst_operand" "rQ")
     76 	     (match_operand:QHSI 1 "h8300_src_operand" "rQi")))]
     77   "reload_completed"
     78   {
     79     if (<MODE>mode == QImode)
     80       return "cmp.b	%X1,%X0";
     81     else if (<MODE>mode == HImode)
     82       return "cmp.w	%T1,%T0";
     83     else if (<MODE>mode == SImode)
     84       return "cmp.l	%S1,%S0";
     85     gcc_unreachable ();
     86   }
     87   [(set_attr "length_table" "add")])
     88 
     89 (define_insn "*cmpqi"
     90   [(set (reg:CC CC_REG)
     91 	(compare (match_operand:QI 0 "h8300_dst_operand" "rQ")
     92 		 (match_operand:QI 1 "h8300_src_operand" "rQi")))]
     93   "reload_completed"
     94   "cmp.b	%X1,%X0"
     95   [(set_attr "length_table" "add")])
     96 
     97 (define_insn "*cmphi"
     98   [(set (reg:CC CC_REG)
     99 	(compare (match_operand:HI 0 "h8300_dst_operand" "rU,rQ")
    100 		 (match_operand:HI 1 "h8300_src_operand" "P3>X,rQi")))]
    101   "reload_completed"
    102 {
    103   switch (which_alternative)
    104     {
    105     case 0:
    106       if (!TARGET_H8300SX)
    107 	return "cmp.w	%T1,%T0";
    108       else
    109 	return "cmp.w	%T1:3,%T0";
    110     case 1:
    111       return "cmp.w	%T1,%T0";
    112     default:
    113       gcc_unreachable ();
    114       }
    115 }
    116   [(set_attr "length_table" "short_immediate,add")])
    117 
    118 (define_insn "cmpsi"
    119   [(set (reg:CC CC_REG)
    120 	(compare (match_operand:SI 0 "h8300_dst_operand" "r,rQ")
    121 		 (match_operand:SI 1 "h8300_src_operand" "P3>X,rQi")))]
    122   "reload_completed"
    123 {
    124   switch (which_alternative)
    125     {
    126     case 0:
    127       if (!TARGET_H8300SX)
    128 	return "cmp.l	%S1,%S0";
    129       else
    130 	return "cmp.l	%S1:3,%S0";
    131     case 1:
    132       return "cmp.l	%S1,%S0";
    133     default:
    134       gcc_unreachable ();
    135     }
    136 }
    137   [(set_attr "length" "2,*")
    138    (set_attr "length_table" "*,add")])
    139 
    140 ;; Convert a memory comparison to a move if there is a scratch register.
    141 
    142 (define_peephole2
    143   [(match_scratch:QHSI 1 "r")
    144    (set (reg:CC CC_REG)
    145 	(compare (match_operand:QHSI 0 "memory_operand" "")
    146 		 (const_int 0)))]
    147   ""
    148   [(parallel [(set (match_dup 1) (match_dup 0)) (clobber (reg:CC CC_REG))])
    149    (set (reg:CC CC_REG) (compare:CC (match_dup 1) (const_int 0)))])
    150 
    151 ;; The compare-elimination pass does not handle memory reference.  So this
    152 ;; little peephole helps fill the gap and avoid code quality regressions.
    153 (define_peephole2
    154   [(parallel [(set (match_operand:QHSI 0 "register_operand" "")
    155 		   (match_operand:QHSI 1 "simple_memory_operand" ""))
    156 	      (clobber (reg:CC CC_REG))])
    157    (set (reg:CCZN CC_REG)
    158 	(compare:CCZN (match_dup 0) (const_int 0)))]
    159   ""
    160   [(parallel [(set (reg:CCZN CC_REG) (compare:CCZN (match_dup 1) (const_int 0)))
    161 	      (set (match_dup 0) (match_dup 1))])])
    162 
    163 ;; This exists solely to convince ifcvt to try some store-flag sequences.
    164 ;;
    165 ;; Essentially we don't want to expose a general store-flag capability.
    166 ;; The only generally useful/profitable case is when we want to test the
    167 ;; C bit.  In that case we can use addx, subx, bst, or bist to get the bit
    168 ;; into a GPR.
    169 ;;
    170 ;; Others could be handled with stc, shifts and masking, but it likely isn't
    171 ;; profitable.
    172 ;;
    173 (define_expand "cstore<mode>4"
    174   [(use (match_operator 1 "eqne_operator"
    175          [(match_operand:QHSI 2 "h8300_dst_operand" "")
    176           (match_operand:QHSI 3 "h8300_src_operand" "")]))
    177    (clobber (match_operand:QHSI 0 "register_operand"))]
    178   ""
    179   {
    180     FAIL;
    181   })
    182 
    183 ;; Storing the C bit is pretty simple since there are many ways to
    184 ;; introduce it into a GPR.  addx, subx and a variety of bit manipulation
    185 ;; instructions
    186 ;;
    187 (define_insn "*store_c_<mode>"
    188   [(set (match_operand:QHSI 0 "register_operand" "=r")
    189 	(eqne:QHSI (reg:CCC CC_REG) (const_int 0)))]
    190   "reload_completed"
    191   {
    192     if (<CODE> == NE)
    193       {
    194 	if (<MODE>mode == QImode)
    195 	  return "xor.b\t%X0,%X0\;bst\t#0,%X0";
    196 	else if (<MODE>mode == HImode)
    197 	  return "xor.w\t%T0,%T0\;bst\t#0,%s0";
    198 	else if (<MODE>mode == SImode)
    199 	  return "xor.l\t%S0,%S0\;bst\t#0,%w0";
    200 	gcc_unreachable ();
    201       }
    202     else if (<CODE> == EQ)
    203       {
    204 	if (<MODE>mode == QImode)
    205 	  return "xor.b\t%X0,%X0\;bist\t#0,%X0";
    206 	else if (<MODE>mode == HImode)
    207 	  return "xor.w\t%T0,%T0\;bist\t#0,%s0";
    208 	else if (<MODE>mode == SImode)
    209 	  return "xor.l\t%S0,%S0\;bist\t#0,%w0";
    210 	gcc_unreachable ();
    211       }
    212   }
    213   [(set (attr "length") (symbol_ref "<MODE>mode == SImode ? 6 : 4"))])
    214 
    215 ;; Similarly, but with a negated result
    216 (define_insn "*store_neg_c_<mode>"
    217   [(set (match_operand:QHSI 0 "register_operand" "=r")
    218 	(neg:QHSI (ne:QHSI (reg:CCC CC_REG) (const_int 0))))]
    219   "reload_completed"
    220   {
    221     if (<MODE>mode == QImode)
    222       return "subx\t%X0,%X0";
    223     else if (<MODE>mode == HImode)
    224       return "subx\t%X0,%X0\;exts.w\t%T0";
    225     else if (<MODE>mode == SImode)
    226       return "subx\t%X0,%X0\;exts.w\t%T0\;exts.l\t%S0";
    227     gcc_unreachable ();
    228   }
    229   [(set
    230      (attr "length")
    231      (symbol_ref "(<MODE>mode == SImode ? 6 : <MODE>mode == HImode ? 4 : 2)"))])
    232 
    233 ;; Using b[i]st we can store the C bit into any of the low 16 bits of
    234 ;; a destination.  We can also rotate it up into the high bit of a 32 bit
    235 ;; destination.
    236 (define_insn "*store_shifted_c<mode>"
    237   [(set (match_operand:QHSI 0 "register_operand" "=r")
    238 	(ashift:QHSI (eqne:QHSI (reg:CCC CC_REG) (const_int 0))
    239 		     (match_operand 1 "immediate_operand" "n")))]
    240   "(reload_completed
    241     && (INTVAL (operands[1]) == 31 || INTVAL (operands[1]) <= 15))"
    242   {
    243     if (<CODE> == NE)
    244       {
    245 	if (<MODE>mode == QImode)
    246 	  return "xor.b\t%X0,%X0\;bst\t%1,%X0";
    247 	else if (<MODE>mode == HImode && INTVAL (operands[1]) < 8)
    248 	  return "xor.w\t%T0,%T0\;bst\t%1,%X0";
    249 	else if (<MODE>mode == HImode)
    250 	  {
    251 	    operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
    252 	    output_asm_insn ("xor.w\t%T0,%T0\;bst\t%1,%t0", operands);
    253 	    return "";
    254 	  }
    255 	else if (<MODE>mode == SImode && INTVAL (operands[1]) == 31)
    256 	  return "xor.l\t%S0,%S0\;rotxr.l\t%S0";
    257 	else if (<MODE>mode == SImode && INTVAL (operands[1]) < 8)
    258 	  return "xor.l\t%S0,%S0\;bst\t%1,%X0";
    259 	else if (<MODE>mode == SImode)
    260 	  {
    261 	    operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
    262 	    output_asm_insn ("xor.l\t%S0,%S0\;bst\t%1,%t0", operands);
    263 	    return "";
    264 	  }
    265 	gcc_unreachable ();
    266       }
    267     else if (<CODE> == EQ)
    268       {
    269 	if (<MODE>mode == QImode)
    270 	  return "xor.b\t%X0,%X0\;bist\t%1,%X0";
    271 	else if (<MODE>mode == HImode && INTVAL (operands[1]) < 8)
    272 	  return "xor.w\t%T0,%T0\;bist\t%1,%X0";
    273 	else if (<MODE>mode == HImode)
    274 	  {
    275 	    operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
    276 	    output_asm_insn ("xor.w\t%T0,%T0\;bist\t%1,%t0", operands);
    277 	    return "";
    278 	  }
    279 	else if (<MODE>mode == SImode && INTVAL (operands[1]) == 31)
    280 	  return "xor.l\t%S0,%S0\;bixor\t#0,%X0\;rotxr.l\t%S0";
    281 	else if (<MODE>mode == SImode && INTVAL (operands[1]) < 8)
    282 	  return "xor.l\t%S0,%S0\;bist\t%1,%X0";
    283 	else if (<MODE>mode == SImode)
    284 	  {
    285 	    operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
    286 	    output_asm_insn ("xor.l\t%S0,%S0\;bist\t%1,%t0", operands);
    287 	    return "";
    288 	  }
    289 	gcc_unreachable ();
    290       }
    291     gcc_unreachable ();
    292   }
    293   [(set
    294      (attr "length")
    295      (symbol_ref "(<MODE>mode == QImode ? 4
    296 		   : <MODE>mode == HImode ? 4
    297 		   : <CODE> == NE ? 6
    298 		   : INTVAL (operands[1]) == 31 ? 8 : 6)"))])
    299 
    300 ;; Recognize this scc and generate code we can match
    301 (define_insn_and_split "*store_c"
    302   [(set (match_operand:QHSI 0 "register_operand" "=r")
    303 	(geultu:QHSI (match_operand:QHSI2 1 "register_operand" "r")
    304 		     (match_operand:QHSI2 2 "register_operand" "r")))]
    305   ""
    306   "#"
    307   "&& reload_completed"
    308   [(set (reg:CCC CC_REG)
    309 	(ltu:CCC (match_dup 1) (match_dup 2)))
    310    (set (match_dup 0)
    311 	(<geultu_to_c>:QHSI (reg:CCC CC_REG) (const_int 0)))])
    312 
    313 ;; We can fold in negation of the result and generate better code than
    314 ;; what the generic bits would do when testing for C == 1
    315 (define_insn_and_split "*store_neg_c"
    316   [(set (match_operand:QHSI 0 "register_operand" "=r")
    317 	(neg:QHSI
    318 	  (ltu:QHSI (match_operand:QHSI2 1 "register_operand" "r")
    319 		    (match_operand:QHSI2 2 "register_operand" "r"))))]
    320   ""
    321   "#"
    322   "&& reload_completed"
    323   [(set (reg:CCC CC_REG)
    324 	(ltu:CCC (match_dup 1) (match_dup 2)))
    325    (set (match_dup 0)
    326 	(neg:QHSI (ne:QHSI (reg:CCC CC_REG) (const_int 0))))])
    327 
    328 ;; We can use rotates and bst/bist to put the C bit into various places
    329 ;; in the destination.
    330 (define_insn_and_split "*store_shifted_c"
    331   [(set (match_operand:QHSI 0 "register_operand" "=r")
    332        (ashift:QHSI (geultu:QHSI (match_operand:QHSI2 1 "register_operand" "r")
    333                                  (match_operand:QHSI2 2 "register_operand" "r"))
    334 		    (match_operand 3 "immediate_operand" "n")))]
    335   "INTVAL (operands[3]) == 31 || INTVAL (operands[3]) <= 15"
    336   "#"
    337   "&& reload_completed"
    338   [(set (reg:CCC CC_REG) (ltu:CCC (match_dup 1) (match_dup 2)))
    339    (set (match_dup 0)
    340 	(ashift:QHSI (<geultu_to_c>:QHSI (reg:CCC CC_REG) (const_int 0))
    341 		     (match_dup 3)))])
    342 
    343