1;; ---------------------------------------------------------------------- 2;; SHIFTS 3;; ---------------------------------------------------------------------- 4;; 5;; We make some attempt to provide real efficient shifting. One example is 6;; doing an 8-bit shift of a 16-bit value by moving a byte reg into the other 7;; reg and moving 0 into the former reg. 8;; 9;; We also try to achieve this in a uniform way. IE: We don't try to achieve 10;; this in both rtl and at insn emit time. Ideally, we'd use rtl as that would 11;; give the optimizer more cracks at the code. However, we wish to do things 12;; like optimizing shifting the sign bit to bit 0 by rotating the other way. 13;; There is rtl to handle this (rotate + and), but the H8/300 doesn't handle 14;; 16-bit rotates. Also, if we emit complicated rtl, combine may not be able 15;; to detect cases it can optimize. 16;; 17;; For these and other fuzzy reasons, I've decided to go the less pretty but 18;; easier "do it at insn emit time" route. 19 20 21(define_expand "ashl<mode>3" 22 [(set (match_operand:QHSI 0 "register_operand" "") 23 (ashift:QHSI (match_operand:QHSI 1 "register_operand" "") 24 (match_operand:QI 2 "nonmemory_operand" "")))] 25 "" 26 { 27 if (expand_a_shift (<MODE>mode, ASHIFT, operands)) 28 DONE; 29 }) 30 31(define_expand "ashr<mode>3" 32 [(set (match_operand:QHSI 0 "register_operand" "") 33 (ashiftrt:QHSI (match_operand:QHSI 1 "register_operand" "") 34 (match_operand:QI 2 "nonmemory_operand" "")))] 35 "" 36 { 37 if (expand_a_shift (<MODE>mode, ASHIFTRT, operands)) 38 DONE; 39 }) 40 41(define_expand "lshr<mode>3" 42 [(set (match_operand:QHSI 0 "register_operand" "") 43 (lshiftrt:QHSI (match_operand:QHSI 1 "register_operand" "") 44 (match_operand:QI 2 "nonmemory_operand" "")))] 45 "" 46 { 47 if (expand_a_shift (<MODE>mode, LSHIFTRT, operands)) 48 DONE; 49 }) 50 51;; QI/HI/SI BIT SHIFTS 52 53(define_insn_and_split "" 54 [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ") 55 (match_operator:QHSI 3 "h8sx_unary_shift_operator" 56 [(match_operand:QHSI 1 "h8300_dst_operand" "0") 57 (match_operand:QI 2 "const_int_operand" "")]))] 58 "h8300_operands_match_p (operands)" 59 "#" 60 "&& reload_completed" 61 [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)])) 62 (clobber (reg:CC CC_REG))])]) 63 64(define_insn "" 65 [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ") 66 (match_operator:QHSI 3 "h8sx_unary_shift_operator" 67 [(match_operand:QHSI 1 "h8300_dst_operand" "0") 68 (match_operand:QI 2 "const_int_operand" "")])) 69 (clobber (reg:CC CC_REG))] 70 "h8300_operands_match_p (operands)" 71{ 72 if (<MODE>mode == E_QImode) 73 return output_h8sx_shift (operands, 'b', 'X'); 74 if (<MODE>mode == E_HImode) 75 return output_h8sx_shift (operands, 'w', 'T'); 76 if (<MODE>mode == E_SImode) 77 return output_h8sx_shift (operands, 'l', 'S'); 78 gcc_unreachable (); 79} 80 [(set_attr "length_table" "unary")]) 81 82(define_insn "" 83 [(set (reg:CCZN CC_REG) 84 (compare:CCZN 85 (match_operator:QHSI 3 "h8sx_unary_shift_operator" 86 [(match_operand:QHSI 1 "h8300_dst_operand" "0") 87 (match_operand:QI 2 "const_int_operand" "")]) 88 (const_int 0))) 89 (set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ") 90 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))] 91 "h8300_operands_match_p (operands)" 92{ 93 if (<MODE>mode == E_QImode) 94 return output_h8sx_shift (operands, 'b', 'X'); 95 if (<MODE>mode == E_HImode) 96 return output_h8sx_shift (operands, 'w', 'T'); 97 if (<MODE>mode == E_SImode) 98 return output_h8sx_shift (operands, 'l', 'S'); 99 gcc_unreachable (); 100} 101 [(set_attr "length_table" "unary")]) 102 103(define_insn_and_split "" 104 [(set (match_operand:QHSI 0 "register_operand" "=r") 105 (match_operator:QHSI 3 "h8sx_binary_shift_operator" 106 [(match_operand:QHSI 1 "register_operand" "0") 107 (match_operand:QI 2 "nonmemory_operand" "r P5>X")]))] 108 "" 109 "#" 110 "&& reload_completed" 111 [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)])) 112 (clobber (reg:CC CC_REG))])]) 113 114(define_insn "" 115 [(set (match_operand:QHSI 0 "register_operand" "=r") 116 (match_operator:QHSI 3 "h8sx_binary_shift_operator" 117 [(match_operand:QHSI 1 "register_operand" "0") 118 (match_operand:QI 2 "nonmemory_operand" "r P5>X")])) 119 (clobber (reg:CC CC_REG))] 120 "" 121{ 122 if (<MODE>mode == QImode) 123 return output_h8sx_shift (operands, 'b', 'X'); 124 if (<MODE>mode == HImode) 125 return output_h8sx_shift (operands, 'w', 'T'); 126 if (<MODE>mode == SImode) 127 return output_h8sx_shift (operands, 'l', 'S'); 128 gcc_unreachable (); 129} 130 [(set_attr "length" "4")]) 131 132(define_insn "" 133 [(set (reg:CCZN CC_REG) 134 (compare:CCZN 135 (match_operator:QHSI 3 "h8sx_binary_shift_operator" 136 [(match_operand:QHSI 1 "register_operand" "0") 137 (match_operand:QI 2 "nonmemory_operand" "r P5>X")]) 138 (const_int 0))) 139 (set (match_operand:QHSI 0 "register_operand" "=r") 140 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))] 141 "" 142{ 143 if (<MODE>mode == QImode) 144 return output_h8sx_shift (operands, 'b', 'X'); 145 if (<MODE>mode == HImode) 146 return output_h8sx_shift (operands, 'w', 'T'); 147 if (<MODE>mode == SImode) 148 return output_h8sx_shift (operands, 'l', 'S'); 149 gcc_unreachable (); 150} 151 [(set_attr "length" "4")]) 152 153(define_insn_and_split "*shiftqi_noscratch" 154 [(set (match_operand:QI 0 "register_operand" "=r,r") 155 (shifts:QI 156 (match_operand:QI 1 "register_operand" "0,0") 157 (match_operand:QI 2 "nonmemory_operand" "R,rn")))] 158 "(GET_CODE (operands[2]) == CONST_INT 159 && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, 160 <CODE>))" 161 "#" 162 "&& reload_completed" 163 [(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2))) 164 (clobber (reg:CC CC_REG))])]) 165 166(define_insn "*shiftqi_noscratch_clobber_flags" 167 [(set (match_operand:QI 0 "register_operand" "=r,r") 168 (shifts:QI 169 (match_operand:QI 1 "register_operand" "0,0") 170 (match_operand:QI 2 "nonmemory_operand" "R,rn"))) 171 (clobber (reg:CC CC_REG))] 172 "(GET_CODE (operands[2]) == CONST_INT 173 && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, <CODE>))" 174{ 175 return output_a_shift (operands, <CODE>); 176} 177 [(set (attr "length") 178 (symbol_ref "compute_a_shift_length (operands, <CODE>)"))]) 179 180(define_insn "*shiftqi_noscratch_set_flags" 181 [(set (reg:CCZN CC_REG) 182 (compare:CCZN 183 (shifts:QI 184 (match_operand:QI 1 "register_operand" "0,0") 185 (match_operand:QI 2 "nonmemory_operand" "R,rn")) 186 (const_int 0))) 187 (set (match_operand:QI 0 "register_operand" "=r,r") 188 (shifts:QI (match_dup 1) (match_dup 2)))] 189 "(GET_CODE (operands[2]) == CONST_INT 190 && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, <CODE>) 191 && compute_a_shift_cc (operands, <CODE>))" 192{ 193 return output_a_shift (operands, <CODE>); 194} 195 [(set (attr "length") 196 (symbol_ref "compute_a_shift_length (operands, <CODE>)"))]) 197 198 199(define_insn_and_split "*shiftqi" 200 [(set (match_operand:QI 0 "register_operand" "=r,r") 201 (shifts:QI 202 (match_operand:QI 1 "register_operand" "0,0") 203 (match_operand:QI 2 "nonmemory_operand" "R,rn"))) 204 (clobber (match_scratch:QI 3 "=X,&r"))] 205 "" 206 "#" 207 "&& reload_completed" 208 [(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2))) 209 (clobber (match_dup 3)) 210 (clobber (reg:CC CC_REG))])]) 211 212(define_insn "*shiftqi_clobber_flags" 213 [(set (match_operand:QI 0 "register_operand" "=r,r") 214 (shifts:QI 215 (match_operand:QI 1 "register_operand" "0,0") 216 (match_operand:QI 2 "nonmemory_operand" "R,rn"))) 217 (clobber (match_scratch:QI 3 "=X,&r")) 218 (clobber (reg:CC CC_REG))] 219 "" 220{ 221 return output_a_shift (operands, <CODE>); 222} 223 [(set (attr "length") 224 (symbol_ref "compute_a_shift_length (operands, <CODE>)"))]) 225 226(define_insn_and_split "*shifthi_noscratch" 227 [(set (match_operand:HI 0 "register_operand" "=r,r") 228 (shifts:HI 229 (match_operand:HI 1 "register_operand" "0,0") 230 (match_operand:HI 2 "nonmemory_operand" "S,rn")))] 231 "(GET_CODE (operands[2]) == CONST_INT 232 && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, <CODE>))" 233 "#" 234 "&& reload_completed" 235 [(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2))) 236 (clobber (reg:CC CC_REG))])]) 237 238(define_insn "*shifthi_noscratch_clobber_flags" 239 [(set (match_operand:HI 0 "register_operand" "=r,r") 240 (shifts:HI 241 (match_operand:HI 1 "register_operand" "0,0") 242 (match_operand:HI 2 "nonmemory_operand" "S,rn"))) 243 (clobber (reg:CC CC_REG))] 244 "(GET_CODE (operands[2]) == CONST_INT 245 && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, <CODE>))" 246{ 247 return output_a_shift (operands, <CODE>); 248} 249 [(set (attr "length") 250 (symbol_ref "compute_a_shift_length (operands, <CODE>)"))]) 251 252(define_insn "*shifthi_noscratch_setzn" 253 [(set (reg:CCZN CC_REG) 254 (compare:CCZN 255 (shifts:HI (match_operand:HI 1 "register_operand" "0,0") 256 (match_operand:HI 2 "nonmemory_operand" "S,rn")) 257 (const_int 0))) 258 (set (match_operand:HI 0 "register_operand" "=r,r") 259 (shifts:HI (match_dup 1) (match_dup 2)))] 260 "(GET_CODE (operands[2]) == CONST_INT 261 && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, <CODE>) 262 && compute_a_shift_cc (operands, <CODE>))" 263{ 264 return output_a_shift (operands, <CODE>); 265} 266 [(set (attr "length") 267 (symbol_ref "compute_a_shift_length (operands, <CODE>)"))]) 268 269(define_insn_and_split "*shifthi" 270 [(set (match_operand:HI 0 "register_operand" "=r,r") 271 (shifts:HI 272 (match_operand:HI 1 "register_operand" "0,0") 273 (match_operand:QI 2 "nonmemory_operand" "S,rn"))) 274 (clobber (match_scratch:QI 3 "=X,&r"))] 275 "" 276 "#" 277 "&& reload_completed" 278 [(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2))) 279 (clobber (match_dup 3)) 280 (clobber (reg:CC CC_REG))])]) 281 282(define_insn "*shifthi_clobber_flags" 283 [(set (match_operand:HI 0 "register_operand" "=r,r") 284 (shifts:HI 285 (match_operand:HI 1 "register_operand" "0,0") 286 (match_operand:QI 2 "nonmemory_operand" "S,rn"))) 287 (clobber (match_scratch:QI 3 "=X,&r")) 288 (clobber (reg:CC CC_REG))] 289 "" 290{ 291 return output_a_shift (operands, <CODE>); 292} 293 [(set (attr "length") 294 (symbol_ref "compute_a_shift_length (operands, <CODE>)"))]) 295 296(define_insn_and_split "*shiftsi_noscratch" 297 [(set (match_operand:SI 0 "register_operand" "=r,r") 298 (shifts:SI 299 (match_operand:SI 1 "register_operand" "0,0") 300 (match_operand:QI 2 "nonmemory_operand" "T,rn")))] 301 "(GET_CODE (operands[2]) == CONST_INT 302 && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, <CODE>))" 303 "#" 304 "&& reload_completed" 305 [(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2))) 306 (clobber (reg:CC CC_REG))])]) 307 308(define_insn "*shiftsi_noscratch_clobber_flags" 309 [(set (match_operand:SI 0 "register_operand" "=r,r") 310 (shifts:SI 311 (match_operand:SI 1 "register_operand" "0,0") 312 (match_operand:SI 2 "nonmemory_operand" "T,rn"))) 313 (clobber (reg:CC CC_REG))] 314 "(GET_CODE (operands[2]) == CONST_INT 315 && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, <CODE>))" 316{ 317 return output_a_shift (operands, <CODE>); 318} 319 [(set (attr "length") 320 (symbol_ref "compute_a_shift_length (operands, <CODE>)"))]) 321 322(define_insn "*shiftsi_noscratch_cczn" 323 [(set (reg:CCZN CC_REG) 324 (compare:CCZN 325 (shifts:SI 326 (match_operand:SI 1 "register_operand" "0,0") 327 (match_operand:SI 2 "nonmemory_operand" "T,rn")) 328 (const_int 0))) 329 (set (match_operand:SI 0 "register_operand" "=r,r") 330 (shifts:SI (match_dup 1) (match_dup 2)))] 331 "(GET_CODE (operands[2]) == CONST_INT 332 && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, <CODE>) 333 && compute_a_shift_cc (operands, <CODE>))" 334{ 335 return output_a_shift (operands, <CODE>); 336} 337 [(set (attr "length") 338 (symbol_ref "compute_a_shift_length (operands, <CODE>)"))]) 339 340;; Split a variable shift into a loop. If the register containing 341;; the shift count dies, then we just use that register. 342 343 344(define_insn_and_split "*shiftsi" 345 [(set (match_operand:SI 0 "register_operand" "=r,r") 346 (shifts:SI 347 (match_operand:SI 1 "register_operand" "0,0") 348 (match_operand:QI 2 "nonmemory_operand" "T,rn"))) 349 (clobber (match_scratch:QI 3 "=X,&r"))] 350 "" 351 "#" 352 "&& reload_completed" 353 [(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2))) 354 (clobber (match_dup 3)) 355 (clobber (reg:CC CC_REG))])]) 356 357(define_insn "*shiftsi_clobber_flags" 358 [(set (match_operand:SI 0 "register_operand" "=r,r") 359 (shifts:SI 360 (match_operand:SI 1 "register_operand" "0,0") 361 (match_operand:QI 2 "nonmemory_operand" "T,rn"))) 362 (clobber (match_scratch:QI 3 "=X,&r")) 363 (clobber (reg:CC CC_REG))] 364 "" 365{ 366 return output_a_shift (operands, <CODE>); 367} 368 [(set (attr "length") 369 (symbol_ref "compute_a_shift_length (operands, <CODE>)"))]) 370 371(define_split 372 [(set (match_operand 0 "register_operand" "") 373 (match_operator 2 "nshift_operator" 374 [(match_dup 0) 375 (match_operand:QI 1 "register_operand" "")])) 376 (clobber (match_operand:QI 3 "register_operand" "")) 377 (clobber (reg:CC CC_REG))] 378 "epilogue_completed 379 && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))" 380 [(set (reg:CCZN CC_REG) 381 (compare:CCZN (match_dup 1) (const_int 0))) 382 (set (pc) 383 (if_then_else (le (reg:CCZN CC_REG) (const_int 0)) 384 (label_ref (match_dup 5)) 385 (pc))) 386 (match_dup 4) 387 (parallel 388 [(set (match_dup 0) 389 (match_op_dup 2 [(match_dup 0) (const_int 1)])) 390 (clobber (reg:CC CC_REG))]) 391 (parallel 392 [(set (reg:CCZN CC_REG) 393 (compare:CCZN 394 (plus:QI (match_dup 1) (const_int -1)) 395 (const_int 0))) 396 (set (match_dup 1) (plus:QI (match_dup 1) (const_int -1)))]) 397 (set (pc) 398 (if_then_else (ne (reg:CCZN CC_REG) (const_int 0)) 399 (label_ref (match_dup 4)) 400 (pc))) 401 (match_dup 5)] 402 { 403 operands[4] = gen_label_rtx (); 404 operands[5] = gen_label_rtx (); 405 }) 406 407(define_split 408 [(set (match_operand 0 "register_operand" "") 409 (match_operator 2 "nshift_operator" 410 [(match_dup 0) 411 (match_operand:QI 1 "register_operand" "")])) 412 (clobber (match_operand:QI 3 "register_operand" "")) 413 (clobber (reg:CC CC_REG))] 414 "epilogue_completed 415 && !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))" 416 [(parallel 417 [(set (reg:CCZN CC_REG) 418 (compare:CCZN (match_dup 1) (const_int 0))) 419 (set (match_dup 3) (match_dup 1))]) 420 (set (pc) 421 (if_then_else (le (reg:CCZN CC_REG) (const_int 0)) 422 (label_ref (match_dup 5)) 423 (pc))) 424 (match_dup 4) 425 (parallel 426 [(set (match_dup 0) 427 (match_op_dup 2 [(match_dup 0) (const_int 1)])) 428 (clobber (reg:CC CC_REG))]) 429 (parallel 430 [(set (reg:CCZN CC_REG) 431 (compare:CCZN 432 (plus:QI (match_dup 3) (const_int -1)) 433 (const_int 0))) 434 (set (match_dup 3) (plus:QI (match_dup 3) (const_int -1)))]) 435 (set (pc) 436 (if_then_else (ne (reg:CCZN CC_REG) (const_int 0)) 437 (label_ref (match_dup 4)) 438 (pc))) 439 (match_dup 5)] 440 { 441 operands[4] = gen_label_rtx (); 442 operands[5] = gen_label_rtx (); 443 }) 444 445(define_split 446 [(set (match_operand:SI 0 "register_operand") 447 (match_operator:SI 3 "nshift_operator" 448 [(match_operand:SI 1 "register_operand") 449 (match_operand:QI 2 "nonmemory_operand")])) 450 (clobber (match_scratch:QI 4))] 451 "reload_completed" 452 [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)])) 453 (clobber (match_dup 4)) 454 (clobber (reg:CC CC_REG))])]) 455 456 457;; ---------------------------------------------------------------------- 458;; ROTATIONS 459;; ---------------------------------------------------------------------- 460 461(define_expand "rotl<mode>3" 462 [(set (match_operand:QHSI 0 "register_operand" "") 463 (rotate:QHSI (match_operand:QHSI 1 "register_operand" "") 464 (match_operand:QI 2 "nonmemory_operand" "")))] 465 "" 466 { 467 if (expand_a_rotate (operands)) 468 DONE; 469 }) 470 471(define_insn_and_split "rotl<mode>3_1" 472 [(set (match_operand:QHSI 0 "register_operand" "=r") 473 (rotate:QHSI (match_operand:QHSI 1 "register_operand" "0") 474 (match_operand:QI 2 "immediate_operand" "")))] 475 "" 476 "#" 477 "&& reload_completed" 478 [(parallel [(set (match_dup 0) (rotate:QHSI (match_dup 1) (match_dup 2))) 479 (clobber (reg:CC CC_REG))])]) 480 481(define_insn "rotl<mode>3_1_clobber_flags" 482 [(set (match_operand:QHSI 0 "register_operand" "=r") 483 (rotate:QHSI (match_operand:QHSI 1 "register_operand" "0") 484 (match_operand:QI 2 "immediate_operand" ""))) 485 (clobber (reg:CC CC_REG))] 486 "" 487{ 488 return output_a_rotate (ROTATE, operands); 489} 490 [(set (attr "length") 491 (symbol_ref "compute_a_rotate_length (operands)"))]) 492