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