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