1;; ---------------------------------------------------------------------- 2;; JUMP INSTRUCTIONS 3;; ---------------------------------------------------------------------- 4 5;; Conditional jump instructions 6 7(define_expand "cbranch<mode>4" 8 [(set (pc) 9 (if_then_else (match_operator 0 "ordered_comparison_operator" 10 [(match_operand:QHSI 1 "h8300_dst_operand") 11 (match_operand:QHSI 2 "h8300_src_operand")]) 12 (label_ref (match_operand 3 "")) 13 (pc)))] 14 "") 15 16(define_insn_and_split "*branch" 17 [(set (pc) 18 (if_then_else (match_operator 0 "comparison_operator" 19 [(match_operand:QHSI 1 "h8300_dst_operand" "rQ") 20 (match_operand:QHSI 2 "h8300_src_operand" "rQi")]) 21 (label_ref (match_operand 3 "" "")) 22 (pc)))] 23 "" 24 "#" 25 "&& reload_completed" 26 [(set (match_dup 4) 27 (match_dup 5)) 28 (set (pc) 29 (if_then_else (match_op_dup 0 30 [(match_dup 4) (const_int 0)]) 31 (label_ref (match_dup 3)) (pc)))] 32 " 33{ 34 machine_mode mode; 35 36 if (REG_P (operands[1]) 37 && operands[2] == const0_rtx 38 && (GET_CODE (operands[0]) == EQ 39 || GET_CODE (operands[0]) == NE 40 || GET_CODE (operands[0]) == LT 41 || GET_CODE (operands[0]) == GE 42 /* Our tstxx insns will set ZN and clear V, so we can handle 43 a couple additional cases. */ 44 || GET_CODE (operands[0]) == LE 45 || GET_CODE (operands[0]) == GT)) 46 mode = E_CCZNmode; 47 else 48 mode = E_CCmode; 49 operands[4] = gen_rtx_REG (mode, CC_REG); 50 operands[5] = gen_rtx_COMPARE (mode, operands[1], operands[2]); 51}") 52 53(define_insn "*branch_1" 54 [(set (pc) 55 (if_then_else (match_operator 1 "comparison_operator" 56 [(reg:H8cc CC_REG) (const_int 0)]) 57 (label_ref (match_operand 0 "" "")) 58 (pc)))] 59 "reload_completed" 60{ 61 if (get_attr_length (insn) == 2) 62 return "b%j1 %l0"; 63 else if (get_attr_length (insn) == 4) 64 return "b%j1 %l0:16"; 65 else 66 return "b%k1 .Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:"; 67} 68 [(set_attr "type" "branch")]) 69 70 71(define_insn "*branch_1_false" 72 [(set (pc) 73 (if_then_else (match_operator 1 "comparison_operator" 74 [(reg:H8cc CC_REG) (const_int 0)]) 75 (pc) 76 (label_ref (match_operand 0 "" ""))))] 77 "reload_completed" 78{ 79 if (get_attr_length (insn) == 2) 80 return "b%k1 %l0"; 81 else if (get_attr_length (insn) == 4) 82 return "b%k1 %l0:16"; 83 else 84 return "b%j1 .Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:"; 85} 86 [(set_attr "type" "branch")]) 87 88;; The brabc/brabs patterns have been disabled because their length computation 89;; is horribly broken. When we call out to a function via a SYMBOL_REF we get 90;; bogus default and minimum lengths. The trick used by the PA port seems to 91;; fix the minimum, but not the default length. The broken lengths can lead 92;; to bogusly using a short jump when a long jump was needed and thus 93;; incorrect code. 94;; 95;; Given the restricted addressing modes for operand 1, we could probably just 96;; open-code the necessary length computation in the two affected patterns 97;; rather than using a function call. I think that would fix this problem. 98(define_insn "*brabc" 99 [(set (pc) 100 (if_then_else (eq (zero_extract (match_operand:QI 1 "bit_memory_operand" "WU") 101 (const_int 1) 102 (match_operand:QI 2 "immediate_operand" "n")) 103 (const_int 0)) 104 (label_ref (match_operand 0 "" "")) 105 (pc)))] 106 "0 && TARGET_H8300SX" 107{ 108 switch (get_attr_length (insn) 109 - h8300_insn_length_from_table (insn, operands)) 110 { 111 case 2: 112 return "bra/bc %2,%R1,%l0"; 113 case 4: 114 return "bra/bc %2,%R1,%l0:16"; 115 default: 116 return "bra/bs %2,%R1,.Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:"; 117 } 118} 119 [(set_attr "type" "bitbranch") 120 (set_attr "length_table" "bitbranch")]) 121 122(define_insn "*brabs" 123 [(set (pc) 124 (if_then_else (ne (zero_extract (match_operand:QI 1 "bit_memory_operand" "WU") 125 (const_int 1) 126 (match_operand:QI 2 "immediate_operand" "n")) 127 (const_int 0)) 128 (label_ref (match_operand 0 "" "")) 129 (pc)))] 130 "0 && TARGET_H8300SX" 131{ 132 switch (get_attr_length (insn) 133 - h8300_insn_length_from_table (insn, operands)) 134 { 135 case 2: 136 return "bra/bs %2,%R1,%l0"; 137 case 4: 138 return "bra/bs %2,%R1,%l0:16"; 139 default: 140 return "bra/bc %2,%R1,.Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:"; 141 } 142} 143 [(set_attr "type" "bitbranch") 144 (set_attr "length_table" "bitbranch")]) 145 146(define_insn_and_split "" 147 [(set (pc) 148 (if_then_else (match_operator 3 "eqne_operator" 149 [(zero_extract:QHSI (match_operand:QHSI 1 "register_operand" "r") 150 (const_int 1) 151 (match_operand 2 "const_int_operand" "n")) 152 (const_int 0)]) 153 (label_ref (match_operand 0 "" "")) 154 (pc)))] 155 "INTVAL (operands[2]) < 16" 156 "#" 157 "&& reload_completed" 158 [(set (reg:CCZ CC_REG) 159 (eq (zero_extract:QHSI (match_dup 1) (const_int 1) (match_dup 2)) 160 (const_int 0))) 161 (set (pc) 162 (if_then_else (match_op_dup 3 [(reg:CCZ CC_REG) (const_int 0)]) 163 (label_ref (match_dup 0)) 164 (pc)))]) 165 166(define_insn_and_split "" 167 [(set (pc) 168 (if_then_else (match_operator 3 "eqne_operator" 169 [(zero_extract:SI (match_operand:SI 1 "register_operand" "r") 170 (const_int 1) 171 (match_operand 2 "const_int_operand" "n")) 172 (const_int 0)]) 173 (label_ref (match_operand 0 "" "")) 174 (pc))) 175 (clobber (match_scratch:SI 4 "=&r"))] 176 "INTVAL (operands[2]) >= 16" 177 "#" 178 "&& reload_completed" 179 [(parallel [(set (match_dup 4) 180 (ior:SI (and:SI (match_dup 4) (const_int -65536)) 181 (lshiftrt:SI (match_dup 1) (const_int 16)))) 182 (clobber (reg:CC CC_REG))]) 183 (set (reg:CCZ CC_REG) 184 (eq (zero_extract:SI (match_dup 4) (const_int 1) (match_dup 2)) 185 (const_int 0))) 186 (set (pc) 187 (if_then_else (match_op_dup 3 [(reg:CCZ CC_REG) (const_int 0)]) 188 (label_ref (match_dup 0)) 189 (pc)))] 190 "operands[2] = GEN_INT (INTVAL (operands[2]) - 16);") 191 192;; Unconditional and other jump instructions. 193 194(define_insn "jump" 195 [(set (pc) 196 (label_ref (match_operand 0 "" "")))] 197 "" 198{ 199 if (final_sequence != 0) 200 { 201 if (get_attr_length (insn) == 2) 202 return "bra/s %l0"; 203 else 204 { 205 /* The branch isn't short enough to use bra/s. Output the 206 branch and delay slot in their normal order. 207 208 If this is a backward branch, it will now be branching two 209 bytes further than previously thought. The length-based 210 test for bra vs. jump is very conservative though, so the 211 branch will still be within range. */ 212 rtx_sequence *seq; 213 int seen; 214 215 seq = final_sequence; 216 final_sequence = 0; 217 final_scan_insn (seq->insn (1), asm_out_file, optimize, 1, & seen); 218 final_scan_insn (seq->insn (0), asm_out_file, optimize, 1, & seen); 219 seq->insn (1)->set_deleted (); 220 return ""; 221 } 222 } 223 else if (get_attr_length (insn) == 2) 224 return "bra %l0"; 225 else if (get_attr_length (insn) == 4) 226 return "bra %l0:16"; 227 else 228 return "jmp @%l0"; 229} 230 [(set_attr "type" "branch") 231 (set (attr "delay_slot") 232 (if_then_else (match_test "TARGET_H8300SX") 233 (const_string "jump") 234 (const_string "none")))]) 235 236;; This is a define expand, because pointers may be either 16 or 32 bits. 237 238(define_expand "tablejump" 239 [(parallel [(set (pc) (match_operand 0 "register_operand" "")) 240 (use (label_ref (match_operand 1 "" "")))])] 241 "" 242 "") 243 244(define_insn "tablejump<mode>" 245 [(set (pc) (match_operand:P 0 "register_operand" "r")) 246 (use (label_ref (match_operand 1 "" "")))] 247 "" 248 { 249 if (<MODE>mode == E_HImode) 250 return "jmp @%0"; 251 if (<MODE>mode == E_SImode) 252 return "jmp @%S0"; 253 abort (); 254 } 255 [(set_attr "length" "2")]) 256 257;; This is a define expand, because pointers may be either 16 or 32 bits. 258 259(define_expand "indirect_jump" 260 [(set (pc) (match_operand 0 "jump_address_operand" ""))] 261 "" 262 "") 263 264(define_insn "*indirect_jump_<mode>" 265 [(set (pc) (match_operand:P 0 "jump_address_operand" "Vr"))] 266 "" 267 { 268 if (<MODE>mode == E_HImode) 269 return "jmp @%0"; 270 if (<MODE>mode == E_SImode) 271 return "jmp @%S0"; 272 abort (); 273 } 274 [(set_attr "length" "2")]) 275 276;; Call subroutine with no return value. 277 278;; ??? Even though we use HImode here, this works on the H8/300H and H8S. 279 280(define_expand "call" 281 [(call (match_operand:QI 0 "call_expander_operand" "") 282 (match_operand 1 "general_operand" ""))] 283 "" 284 { 285 if (!register_operand (XEXP (operands[0], 0), Pmode) 286 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF) 287 XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0)); 288 }) 289 290(define_insn "call_insn_<mode>" 291 [(call (mem:QI (match_operand 0 "call_insn_operand" "Cr")) 292 (match_operand:P 1 "general_operand" "g"))] 293 "!SIBLING_CALL_P (insn)" 294{ 295 rtx xoperands[1]; 296 xoperands[0] = gen_rtx_MEM (QImode, operands[0]); 297 gcc_assert (GET_MODE (operands[0]) == Pmode); 298 if (GET_CODE (XEXP (xoperands[0], 0)) == SYMBOL_REF 299 && (SYMBOL_REF_FLAGS (XEXP (xoperands[0], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) 300 output_asm_insn ("jsr\\t@%0:8", xoperands); 301 else 302 output_asm_insn ("jsr\\t%0", xoperands); 303 return ""; 304} 305 [(set_attr "type" "call") 306 (set (attr "length") 307 (if_then_else (match_operand:QI 0 "small_call_insn_operand" "") 308 (const_int 2) 309 (const_int 4)))]) 310 311;; Call subroutine, returning value in operand 0 312;; (which must be a hard register). 313 314;; ??? Even though we use HImode here, this works on the H8/300H and H8S. 315 316(define_expand "call_value" 317 [(set (match_operand 0 "" "") 318 (call (match_operand:QI 1 "call_expander_operand" "") 319 (match_operand 2 "general_operand" "")))] 320 "" 321 { 322 if (!register_operand (XEXP (operands[1], 0), Pmode) 323 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF) 324 XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0)); 325 }) 326 327(define_insn "call_value_insn_<mode>" 328 [(set (match_operand 0 "" "=r") 329 (call (mem:QI (match_operand 1 "call_insn_operand" "Cr")) 330 (match_operand:P 2 "general_operand" "g")))] 331 "!SIBLING_CALL_P (insn)" 332{ 333 rtx xoperands[2]; 334 gcc_assert (GET_MODE (operands[1]) == Pmode); 335 xoperands[0] = operands[0]; 336 xoperands[1] = gen_rtx_MEM (QImode, operands[1]); 337 if (GET_CODE (XEXP (xoperands[1], 0)) == SYMBOL_REF 338 && (SYMBOL_REF_FLAGS (XEXP (xoperands[1], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) 339 output_asm_insn ("jsr\\t@%1:8", xoperands); 340 else 341 output_asm_insn ("jsr\\t%1", xoperands); 342 return ""; 343} 344 [(set_attr "type" "call") 345 (set (attr "length") 346 (if_then_else (match_operand:QI 0 "small_call_insn_operand" "") 347 (const_int 2) 348 (const_int 4)))]) 349 350(define_expand "sibcall" 351 [(call (match_operand:QI 0 "call_expander_operand" "") 352 (match_operand 1 "general_operand" ""))] 353 "" 354 { 355 if (!register_operand (XEXP (operands[0], 0), Pmode) 356 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF) 357 XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0)); 358 }) 359 360(define_insn "sibcall_insn_<mode>" 361 [(call (mem:QI (match_operand 0 "call_insn_operand" "Cr")) 362 (match_operand:P 1 "general_operand" "g"))] 363 "SIBLING_CALL_P (insn)" 364{ 365 rtx xoperands[1]; 366 xoperands[0] = gen_rtx_MEM (QImode, operands[0]); 367 gcc_assert (GET_MODE (operands[0]) == Pmode); 368 if (GET_CODE (XEXP (xoperands[0], 0)) == SYMBOL_REF 369 && (SYMBOL_REF_FLAGS (XEXP (xoperands[0], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) 370 output_asm_insn ("jmp\\t@%0:8", xoperands); 371 else 372 output_asm_insn ("jmp\\t%0", xoperands); 373 return ""; 374} 375 [(set_attr "type" "call") 376 (set (attr "length") 377 (if_then_else (match_operand:QI 0 "small_call_insn_operand" "") 378 (const_int 2) 379 (const_int 4)))]) 380 381;; Call subroutine, returning value in operand 0 382;; (which must be a hard register). 383 384;; ??? Even though we use HImode here, this works on the H8/300H and H8S. 385 386(define_expand "sibcall_value" 387 [(set (match_operand 0 "" "") 388 (call (match_operand:QI 1 "call_expander_operand" "") 389 (match_operand 2 "general_operand" "")))] 390 "" 391 { 392 if (!register_operand (XEXP (operands[1], 0), Pmode) 393 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF) 394 XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0)); 395 }) 396 397(define_insn "sibcall_value_insn_<mode>" 398 [(set (match_operand 0 "" "=r") 399 (call (mem:QI (match_operand 1 "call_insn_operand" "Cr")) 400 (match_operand:P 2 "general_operand" "g")))] 401 "SIBLING_CALL_P (insn)" 402{ 403 rtx xoperands[2]; 404 gcc_assert (GET_MODE (operands[1]) == Pmode); 405 xoperands[0] = operands[0]; 406 xoperands[1] = gen_rtx_MEM (QImode, operands[1]); 407 if (GET_CODE (XEXP (xoperands[1], 0)) == SYMBOL_REF 408 && (SYMBOL_REF_FLAGS (XEXP (xoperands[1], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) 409 output_asm_insn ("jmp\\t@%1:8", xoperands); 410 else 411 output_asm_insn ("jmp\\t%1", xoperands); 412 return ""; 413} 414 [(set_attr "type" "call") 415 (set (attr "length") 416 (if_then_else (match_operand:QI 0 "small_call_insn_operand" "") 417 (const_int 2) 418 (const_int 4)))]) 419 420