1 ;; Machine Description for TI MSP43* processors 2 ;; Copyright (C) 2013-2022 Free Software Foundation, Inc. 3 ;; Contributed by Red Hat. 4 5 ;; This file is part of GCC. 6 7 ;; GCC is free software; you can redistribute it and/or modify 8 ;; it under the terms of the GNU General Public License as published by 9 ;; the Free Software Foundation; either version 3, or (at your option) 10 ;; any later version. 11 12 ;; GCC is distributed in the hope that it will be useful, 13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 ;; GNU General Public License for more details. 16 17 ;; You should have received a copy of the GNU General Public License 18 ;; along with GCC; see the file COPYING3. If not see 19 ;; <http://www.gnu.org/licenses/>. 20 22 23 (define_constants 24 [ 25 (PC_REGNO 0) 26 (SP_REGNO 1) 27 (CARRY 2) 28 ]) 29 30 (define_c_enum "unspec" 31 [ 32 UNS_PROLOGUE_START_MARKER 33 UNS_PROLOGUE_END_MARKER 34 UNS_EPILOGUE_START_MARKER 35 UNS_EPILOGUE_HELPER 36 37 UNS_PUSHM 38 UNS_POPM 39 40 UNS_GROW_AND_SWAP 41 UNS_SWAP_AND_SHRINK 42 43 UNS_DINT 44 UNS_EINT 45 UNS_PUSH_INTR 46 UNS_POP_INTR 47 UNS_BIC_SR 48 UNS_BIS_SR 49 50 UNS_REFSYM_NEED_EXIT 51 52 UNS_DELAY_32 53 UNS_DELAY_32X 54 UNS_DELAY_16 55 UNS_DELAY_16X 56 UNS_DELAY_2 57 UNS_DELAY_1 58 UNS_DELAY_START 59 UNS_DELAY_END 60 ]) 61 62 ;; Instruction length is calculated by examining the type and number of 63 ;; operands. 64 ;; Whether the insn uses the 430X extension word, or is a 430X address 65 ;; instruction also has an effect. 66 ;; "Cheap" source operands do not contribute to the overall length of the insn 67 ;; and are register (Rn), indirect post-increment (@Rn+) and indirect register 68 ;; (@Rn). 69 ;; The lengths of instructions in bytes are: 70 ;; Single-op 430: Cheap op == 2 71 ;; (also CALLA) Other op == 4 72 ;; Double-op 430: Source is not cheap == 2 73 ;; (also MOVA, Dest is register == 2 74 ;; CMPA, ADDA, Dest is not a register == 4 75 ;; SUBA) (sum the source and dest cost) 76 ;; Single-op 430X: For insn names ending in 'X' add 2 to single-op 430 cost. 77 ;; Double-op 430X: Insn name ends in 'M' == 2 78 ;; Others have the same cost as double-op 430 but add 2. 79 ;; 80 ;; The insn type describes whether it is a single or double operand MSP430 81 ;; instruction (some single-operand GCC instructions are actually 82 ;; double-operand on the target). 83 ;; "triple" and "cmp" types use the costs of a double operand type but 84 ;; instead assume that the src operand is in op2, and also cmp types assume the 85 ;; dst operand is in op1. 86 ;; This attribute also describes which operands are safe to examine 87 ;; when calculating the length or extension. GCC will segfault trying to 88 ;; examine a non-existant operand of an insn. 89 (define_attr "type" "none,single,double,triple,cmp" (const_string "none")) 90 91 ;; The M extension is for instructions like RRAM - they always 92 ;; only, and the operand must be a register. 93 (define_attr "extension" "none,x,a,m" 94 (cond [(eq_attr "type" "none") 95 (const_string "none") 96 (match_operand 0 "msp430_high_memory_operand" "") 97 (const_string "x") 98 (and (eq_attr "type" "double") 99 (match_operand 1 "msp430_high_memory_operand" "")) 100 (const_string "x") 101 (and (ior (eq_attr "type" "triple") (eq_attr "type" "cmp")) 102 (ior (match_operand 1 "msp430_high_memory_operand" "") 103 (match_operand 2 "msp430_high_memory_operand" ""))) 104 (const_string "x")] 105 (const_string "none"))) 106 107 ;; Multiply the default length by this constant value. 108 (define_attr "length_multiplier" "" (const_int 1)) 109 110 ;; Add an additional amount to the total length of the insn. 111 (define_attr "extra_length" "" (const_int 0)) 112 113 ;; FIXME for some reason if we move the addition of 2 for extension == x to 114 ;; ADJUST_INSN_LENGTH, codesize gets much worse. 115 (define_attr "length" "" 116 (cond [(eq_attr "extension" "m") 117 (const_int 2) 118 (eq_attr "type" "single") 119 (plus (if_then_else (match_operand 0 "msp430_cheap_operand" "") 120 (const_int 2) 121 (const_int 4)) 122 (if_then_else (eq_attr "extension" "x") 123 (const_int 2) 124 (const_int 0))) 125 (eq_attr "type" "double") 126 (plus (plus (if_then_else (match_operand 0 "register_operand" "") 127 (const_int 2) 128 (const_int 4)) 129 (if_then_else (match_operand 1 "msp430_cheap_operand" "") 130 (const_int 0) 131 (const_int 2))) 132 (if_then_else (eq_attr "extension" "x") 133 (const_int 2) 134 (const_int 0))) 135 (eq_attr "type" "triple") 136 (plus (plus (if_then_else (match_operand 0 "register_operand" "") 137 (const_int 2) 138 (const_int 4)) 139 (if_then_else (match_operand 2 "msp430_cheap_operand" "") 140 (const_int 0) 141 (const_int 2))) 142 (if_then_else (eq_attr "extension" "x") 143 (const_int 2) 144 (const_int 0))) 145 (eq_attr "type" "cmp") 146 (plus (plus (if_then_else (match_operand 1 "register_operand" "") 147 (const_int 2) 148 (const_int 4)) 149 (if_then_else (match_operand 2 "msp430_cheap_operand" "") 150 (const_int 0) 151 (const_int 2))) 152 (if_then_else (eq_attr "extension" "x") 153 (const_int 2) 154 (const_int 0)))] 155 (const_int 2))) 156 157 (include "predicates.md") 158 (include "constraints.md") 159 160 (define_mode_iterator QHI [QI HI PSI]) 161 (define_mode_iterator HPSI [HI PSI]) 162 (define_mode_iterator HDI [HI PSI SI DI]) 163 164 ;; Mapping of all shift operators 165 (define_code_iterator any_shift [ashift ashiftrt lshiftrt]) 166 167 ;; Base name for define_insn 168 (define_code_attr shift_insn 169 [(ashift "ashl") (lshiftrt "lshr") (ashiftrt "ashr")]) 170 171 ;; There are two basic "family" tests we do here: 172 ;; 173 ;; msp430x - true if 430X instructions are available. 174 ;; TARGET_LARGE - true if pointers are 20-bits 175 ;; 176 ;; Note that there are three supported cases, since the base 430 177 ;; doesn't have 20-bit pointers: 178 ;; 179 ;; 1. MSP430 cpu, small model 180 ;; 2. MSP430X cpu, small model. 181 ;; 3. MSP430X cpu, large model. 182 183 ;;------------------------------------------------------------ 184 ;; Moves 185 186 ;; Push/Pop must be before the generic move patterns 187 188 (define_insn "push" 189 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNO))) 190 (match_operand:HI 0 "register_operand" "r"))] 191 "" 192 "PUSH\t%0" 193 [(set_attr "type" "single")] 194 ) 195 196 (define_insn "pusha" 197 [(set (mem:PSI (pre_dec:PSI (reg:PSI SP_REGNO))) 198 (match_operand:PSI 0 "register_operand" "r"))] 199 "TARGET_LARGE" 200 "PUSHX.A\t%0" 201 [(set_attr "type" "single") 202 (set_attr "extension" "x")] 203 ) 204 205 (define_insn "pushm" 206 [(unspec_volatile [(match_operand 0 "register_operand" "r") 207 (match_operand 1 "immediate_operand" "n")] UNS_PUSHM)] 208 "" 209 "PUSHM%b0\t%1, %0" 210 [(set_attr "type" "single") 211 (set_attr "extension" "m")] 212 ) 213 214 (define_insn "pop" 215 [(set (match_operand:HI 0 "register_operand" "=r") 216 (mem:HI (post_inc:HI (reg:HI SP_REGNO))))] 217 "" 218 "POP\t%0" 219 [(set_attr "type" "single")] 220 ) 221 222 (define_insn "popa" 223 [(set (match_operand:PSI 0 "register_operand" "=r") 224 (mem:PSI (post_inc:PSI (reg:PSI SP_REGNO))))] 225 "TARGET_LARGE" 226 "POPX.A\t%0" 227 [(set_attr "type" "single") 228 (set_attr "extension" "x")] 229 ) 230 231 ;; This is nasty. Operand0 is bogus. It is only there so that we can get a 232 ;; mode for the %b0 to work. We should use operand1 for this, but that does 233 ;; not have a mode. 234 ;; 235 ;; Operand1 is actually a register, but we cannot accept (REG...) because the 236 ;; cprop_hardreg pass can and will renumber registers even inside 237 ;; unspec_volatiles. So we take an integer register number parameter and 238 ;; fudge it to be a register name when we generate the assembler. 239 ;; 240 ;; The pushm pattern does not have this problem because of all of the 241 ;; frame info cruft attached to it, so cprop_hardreg leaves it alone. 242 (define_insn "popm" 243 [(unspec_volatile [(match_operand 0 "register_operand" "r") 244 (match_operand 1 "immediate_operand" "i") 245 (match_operand 2 "immediate_operand" "i")] UNS_POPM)] 246 "" 247 "POPM%b0\t%2, r%J1" 248 [(set_attr "type" "single") 249 (set_attr "extension" "m")] 250 ) 251 252 ;; The next two patterns are here to support a "feature" of how GCC implements 253 ;; varargs. When a function uses varargs and the *second* to last named 254 ;; argument is split between argument registers and the stack, gcc expects the 255 ;; callee to allocate space on the stack that can contain the register-based 256 ;; part of the argument. This space *has* to be just before the remaining 257 ;; arguments (ie the ones that are fully on the stack). 258 ;; 259 ;; The problem is that the MSP430 CALL instruction pushes the return address 260 ;; onto the stack in the exact place where the callee wants to allocate 261 ;; this extra space. So we need a sequence of instructions that can allocate 262 ;; the extra space and then move the return address down the stack, so that 263 ;; the extra space is now adjacent to the remaining arguments. 264 ;; 265 ;; This could be constructed through regular insns, but they might be split up 266 ;; by a misguided optimization, so an unspec volatile is used instead. 267 268 (define_insn "grow_and_swap" 269 [(unspec_volatile [(const_int 0)] UNS_GROW_AND_SWAP)] 270 "" 271 "* 272 if (TARGET_LARGE) 273 return \"SUBA\t#2, r1 { MOVX.A\t2(r1), 0(r1)\"; 274 return \"SUB\t#2, r1 { MOV.W\t2(r1), 0(r1)\"; 275 " 276 [(set (attr "length") 277 (if_then_else (match_test "TARGET_LARGE") 278 (const_int 8) 279 (const_int 6)))] 280 ) 281 282 (define_insn "swap_and_shrink" 283 [(unspec_volatile [(const_int 0)] UNS_SWAP_AND_SHRINK)] 284 "" 285 "* return TARGET_LARGE 286 ? \"MOVX.A\t0(r1), 2(r1) { ADDA\t#2, SP\" 287 : \"MOV.W\t0(r1), 2(r1) { ADD\t#2, SP\"; 288 " 289 [(set (attr "length") 290 (if_then_else (match_test "TARGET_LARGE") 291 (const_int 10) 292 (const_int 8)))] 293 ) 294 295 ; I set LOAD_EXTEND_OP and WORD_REGISTER_OPERATIONS, but gcc puts in a 296 ; zero_extend anyway. Catch it here. 297 (define_insn "movqihi" 298 [(set (match_operand:HI 0 "register_operand" "=r,r") 299 (zero_extend:HI (match_operand:QI 1 "memory_operand" "Ys,m")))] 300 "" 301 "@ 302 MOV.B\t%1, %0 303 MOV%X1.B\t%1, %0" 304 [(set_attr "type" "double")] 305 ) 306 307 (define_insn "movqi_topbyte" 308 [(set (match_operand:QI 0 "msp430_general_dst_operand" "=r") 309 (subreg:QI (match_operand:PSI 1 "msp430_general_operand" "r") 2))] 310 "msp430x" 311 "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0" 312 [(set_attr "length" "6") 313 (set_attr "type" "double")] 314 ) 315 316 (define_insn "movqi" 317 [(set (match_operand:QI 0 "msp430_general_dst_operand" "=rYsYx,rm") 318 (match_operand:QI 1 "msp430_general_operand" "riYsYx,rmi"))] 319 "" 320 "@ 321 MOV.B\t%1, %0 322 MOVX.B\t%1, %0" 323 [(set_attr "type" "double")] 324 ) 325 326 (define_insn "movhi" 327 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=r,rYsYx,rm") 328 (match_operand:HI 1 "msp430_general_operand" "N,riYsYx,rmi"))] 329 "" 330 "@ 331 MOV.B\t%1, %0 332 MOV.W\t%1, %0 333 MOVX.W\t%1, %0" 334 [(set_attr "type" "double")] 335 ) 336 337 (define_expand "movsi" 338 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand") 339 (match_operand:SI 1 "general_operand"))] 340 "" 341 "" 342 ) 343 344 (define_insn_and_split "movsi_s" 345 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm") 346 (subreg:SI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))] 347 "" 348 "" 349 "reload_completed" 350 [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand") 351 (match_operand:HI 4 "general_operand")) 352 (set (match_operand:HI 3 "msp430_general_dst_nonv_operand") 353 (match_operand:HI 5 "general_operand"))] 354 "msp430_split_movsi (operands);" 355 [(set_attr "type" "double")] 356 ) 357 358 (define_insn_and_split "movsi_x" 359 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm") 360 (match_operand:SI 1 "general_operand" "rmi"))] 361 "" 362 "#" 363 "reload_completed" 364 [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand") 365 (match_operand:HI 4 "general_operand")) 366 (set (match_operand:HI 3 "msp430_general_dst_nonv_operand") 367 (match_operand:HI 5 "general_operand"))] 368 "msp430_split_movsi (operands);" 369 [(set_attr "type" "double")] 370 ) 371 372 ;; FIXME: Some MOVX.A cases can be done with MOVA, this is only a few of them. 373 (define_insn "movpsi" 374 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,r,r,Ya,rm") 375 (match_operand:PSI 1 "msp430_general_operand" "N,O,riYa,r,rmi"))] 376 "" 377 "@ 378 MOV.B\t%1, %0 379 MOV.W\t%1, %0 380 MOVA\t%1, %0 381 MOVA\t%1, %0 382 MOVX.A\t%1, %0" 383 [(set_attr "extension" "none,none,a,a,x") 384 (set_attr "type" "double")] 385 ) 386 387 ; This pattern is identical to the truncsipsi2 pattern except 388 ; that it uses a SUBREG instead of a TRUNC. It is needed in 389 ; order to prevent reload from converting (set:SI (SUBREG:PSI (SI))) 390 ; into (SET:PSI (PSI)). 391 ; 392 ; Note: using POPM.A #1 is two bytes smaller than using POPX.A.... 393 394 (define_insn "movsipsi2" 395 [(set (match_operand:PSI 0 "register_operand" "=r") 396 (subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))] 397 "msp430x" 398 "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0" 399 [(set_attr "length" "6") 400 (set_attr "type" "double")] 401 ) 402 403 ;; Produced when converting a pointer to an integer via a union, eg gcc.dg/pr47201.c. 404 (define_insn "*movpsihi2_lo" 405 [(set (match_operand:HI 0 "register_operand" "=r") 406 (subreg:HI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))] 407 "msp430x" 408 "MOVA\t%1, %0" 409 [(set_attr "extension" "a") 410 (set_attr "type" "double")] 411 ) 412 413 ;;------------------------------------------------------------ 414 ;; Math 415 416 (define_insn "addpsi3" 417 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,rm") 418 (plus:PSI (match_operand:PSI 1 "msp430_general_operand" "%0,0") 419 (match_operand:PSI 2 "msp430_general_operand" "rLs,rmi")))] 420 "" 421 "@ 422 ADDA\t%2, %0 423 ADDX.A\t%2, %0" 424 [(set_attr "extension" "a,x") 425 (set_attr "type" "triple")] 426 ) 427 428 (define_insn "addqi3" 429 [(set (match_operand:QI 0 "msp430_general_dst_operand" "=rYsYx,rm") 430 (plus:QI (match_operand:QI 1 "msp430_general_operand" "%0,0") 431 (match_operand:QI 2 "msp430_general_operand" "riYsYx,rmi")))] 432 "" 433 "@ 434 ADD.B\t%2, %0 435 ADDX.B\t%2, %0" 436 [(set_attr "type" "triple")] 437 ) 438 439 (define_insn "addhi3" 440 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm") 441 (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0") 442 (match_operand:HI 2 "msp430_general_operand" "riYsYx,rmi")))] 443 "" 444 "@ 445 ADD.W\t%2, %0 446 ADDX.W\t%2, %0" 447 [(set_attr "type" "triple")] 448 ) 449 450 ; This pattern is needed in order to avoid reload problems. 451 ; It takes an SI pair of registers, adds a value to them, and 452 ; then converts them into a single PSI register. 453 454 (define_insn "addsipsi3" 455 [(set (subreg:SI (match_operand:PSI 0 "register_operand" "=&r") 0) 456 (plus:SI (match_operand:SI 1 "register_operand" "0") 457 (match_operand 2 "general_operand" "rmi")))] 458 "" 459 "ADD%X2.W\t%L2, %L0 { ADDC%X2.W\t%H2, %H0 { PUSH.W\t%H0 { PUSH.W\t%L0 { POPM.A\t#1, %0" 460 [(set (attr "length") 461 (if_then_else (match_operand 2 "register_operand" "") 462 (const_int 10) 463 (if_then_else (match_operand 2 "msp430_high_memory_operand" "") 464 (const_int 18) 465 (const_int 14)))) 466 (set_attr "type" "triple")] 467 ) 468 469 (define_insn "addsi3" 470 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=&rYsYx,rm") 471 (plus:SI (match_operand:SI 1 "general_operand" "%0,0") 472 (match_operand:SI 2 "general_operand" "rYsYxi,mi")))] 473 "" 474 "@ 475 ADD\t%L2, %L0 { ADDC\t%H2, %H0 476 ADDX\t%L2, %L0 { ADDCX\t%H2, %H0" 477 [(set_attr "length_multiplier" "2") 478 (set_attr "type" "triple")] 479 ) 480 481 ; Version of addhi that exposes the carry operations, for SImode adds. 482 ; 483 ; NOTE - we are playing a dangerous game with GCC here. We have these two 484 ; add patterns and the splitter that follows because our tests have shown 485 ; that this results in a significant reduction in code size - because GCC is 486 ; able to discard any unused part of the addition. We have to annotate the 487 ; patterns with the set and use of the carry flag because otherwise GCC will 488 ; discard parts of the addition when they are actually needed. But we have 489 ; not annotated all the other patterns that set the CARRY flag as doing so 490 ; results in an overall increase in code size[1]. Instead we just *hope* 491 ; that GCC will not move a carry-setting instruction in between the first 492 ; and second adds. 493 ; 494 ; So far our experiments have shown that GCC is likely to move MOV and CMP 495 ; instructions in between the two adds, but not other instructions. MOV is 496 ; safe, CMP is not. So we have annotated the CMP patterns and left the 497 ; subtract, shift and other add patterns alone. At the moment this is 498 ; working, but with future changes to the generic parts of GCC that might 499 ; change. 500 ; 501 ; [1] It is not clear exactly why the code size increases. The cause appears 502 ; to be that reload is more prevelent to spilling a variable onto the stack 503 ; but why it does this is unknown. Possibly the additional CLOBBERs necessary 504 ; to correctly annotate the other patterns makes reload think that there is 505 ; increased register pressure. Or possibly reload does not handle ADD patterns 506 ; that are not single_set() very well. 507 508 ; match_operand 3 is likely to be the same as op2 most of the time - except 509 ; when op2 is a post_inc and we have stripped the post_inc from match_operand 3 510 511 (define_insn "addhi3_cy" 512 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm") 513 (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0") 514 (match_operand:HI 2 "msp430_nonimmediate_operand" "rYsYxi,rm"))) 515 (set (reg:BI CARRY) 516 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1)) 517 (zero_extend:SI (match_operand:HI 3 "msp430_nonimmediate_operand" "rYsYxi,rm"))) 518 (const_int 16)))) 519 ] 520 "" 521 "@ 522 ADD\t%2, %1 ; cy 523 ADDX\t%2, %1 ; cy" 524 [(set_attr "type" "triple")] 525 ) 526 527 (define_insn "addhi3_cy_i" 528 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=r,rm") 529 (plus:HI (match_operand:HI 1 "general_operand" "%0,0") 530 (match_operand:HI 2 "immediate_operand" "i,i"))) 531 (set (reg:BI CARRY) 532 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1)) 533 (match_operand 3 "immediate_operand" "i,i")) 534 (const_int 16)))) 535 ] 536 "" 537 "@ 538 ADD\t%2, %1 ; cy 539 ADD%X0\t%2, %1 ; cy" 540 [(set_attr "type" "triple")] 541 ) 542 543 ; Version of addhi that adds the carry, for SImode adds. 544 (define_insn "addchi4_cy" 545 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm") 546 (plus:HI (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0") 547 (match_operand:HI 2 "msp430_general_operand" "riYsYx,rmi")) 548 (zero_extend:HI (reg:BI CARRY)))) 549 ] 550 "" 551 "@ 552 ADDC\t%2, %1 553 ADDCX\t%2, %1" 554 [(set_attr "type" "triple")] 555 ) 556 557 ; Split an SImode add into two HImode adds, keeping track of the carry 558 ; so that gcc knows when it can and can't optimize away the two 559 ; halves. 560 ; We use the ugly predicate "msp430_nonsubregnonpostinc_or_imm_operand" to 561 ; enforce the position of a post_inc into op2 if present 562 (define_split 563 [(set (match_operand:SI 0 "msp430_nonsubreg_dst_operand") 564 (plus:SI (match_operand:SI 1 "msp430_nonsubregnonpostinc_or_imm_operand") 565 (match_operand:SI 2 "msp430_nonsubreg_or_imm_operand"))) 566 ] 567 "" 568 [(parallel [(set (match_operand:HI 3 "msp430_general_dst_nonv_operand" "=&rm") 569 (plus:HI (match_dup 4) 570 (match_dup 5))) 571 (set (reg:BI CARRY) 572 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 4)) 573 (match_dup 9)) 574 (const_int 16)))) 575 ]) 576 (set (match_operand:HI 6 "msp430_general_dst_nonv_operand" "=&rm") 577 (plus:HI (plus:HI (match_dup 7) 578 (match_dup 8)) 579 (zero_extend:HI (reg:BI CARRY)))) 580 ] 581 " 582 if (msp430_split_addsi (operands)) 583 FAIL; 584 " 585 ) 586 587 588 ;; Alternatives 2 and 3 are to handle cases generated by reload. 589 (define_insn "subpsi3" 590 [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r, rm, &?r, ?&r") 591 (minus:PSI (match_operand:PSI 1 "general_operand" "0, 0, !r, !i") 592 (match_operand:PSI 2 "general_operand" "rLs, rmi, rmi, r")))] 593 "" 594 "@ 595 SUBA\t%2, %0 596 SUBX.A\t%2, %0 597 MOVX.A\t%1, %0 { SUBX.A\t%2, %0 598 MOVX.A\t%1, %0 { SUBA\t%2, %0" 599 [(set_attr "type" "triple") 600 (set_attr "extension" "a,x,x,x") 601 (set_attr "length_multiplier" "1,1,2,2")] 602 ) 603 604 ;; Alternatives 2 and 3 are to handle cases generated by reload. 605 (define_insn "subqi3" 606 [(set (match_operand:QI 0 "msp430_general_dst_nonv_operand" "=rYsYx, rm, &?r, ?&r") 607 (minus:QI (match_operand:QI 1 "general_operand" "0, 0, !r, !i") 608 (match_operand:QI 2 "general_operand" " riYsYx, rmi, rmi, r")))] 609 "" 610 "@ 611 SUB.B\t%2, %0 612 SUBX.B\t%2, %0 613 MOV%X2.B\t%1, %0 { SUB%X2.B\t%2, %0 614 MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0" 615 [(set_attr "length_multiplier" "1,1,2,2") 616 (set_attr "type" "triple")] 617 ) 618 619 ;; Alternatives 2 and 3 are to handle cases generated by reload. 620 (define_insn "subhi3" 621 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=rYsYx, rm, &?r, ?&r") 622 (minus:HI (match_operand:HI 1 "general_operand" "0, 0, !r, !i") 623 (match_operand:HI 2 "general_operand" " riYsYx, rmi, rmi, r")))] 624 "" 625 "@ 626 SUB.W\t%2, %0 627 SUBX.W\t%2, %0 628 MOV%X2.W\t%1, %0 { SUB%X2.W\t%2, %0 629 MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0" 630 [(set_attr "length_multiplier" "1,1,2,2") 631 (set_attr "type" "triple")] 632 ) 633 634 (define_insn "subsi3" 635 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=&rYsYx,m") 636 (minus:SI (match_operand:SI 1 "general_operand" "0,0") 637 (match_operand:SI 2 "general_operand" "riYsYx,mi")))] 638 "" 639 "@ 640 SUB\t%L2, %L0 { SUBC\t%H2, %H0 641 SUBX\t%L2, %L0 { SUBCX\t%H2, %H0" 642 [(set_attr "length_multiplier" "2") 643 (set_attr "type" "triple")] 644 ) 645 646 (define_insn "*bic<mode>_cg" 647 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYs,m") 648 (and:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0") 649 (match_operand 2 "msp430_inv_constgen_operator" "n,n")))] 650 "" 651 "@ 652 BIC%x0%b0\t#%I2, %0 653 BIC%X0%b0\t#%I2, %0" 654 [(set_attr "length" "2") ; Smaller length achieved by using constant generator 655 (set_attr "type" "double")] 656 ) 657 658 (define_insn "bic<mode>3" 659 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm") 660 (and:QHI (not:QHI (match_operand:QHI 1 "msp430_general_operand" "rYsYx,rmn")) 661 (match_operand:QHI 2 "msp430_general_operand" "0,0")))] 662 "" 663 "@ 664 BIC%x0%b0\t%1, %0 665 BICX%b0\t%1, %0" 666 [(set_attr "type" "double")] 667 ) 668 669 (define_insn "and<mode>3" 670 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=r,rYsYx,rm") 671 (and:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0,0") 672 (match_operand:QHI 2 "msp430_general_operand" "N,riYsYx,rmi")))] 673 "" 674 "@ 675 AND%x0.B\t%2, %0 676 AND%x0%b0\t%2, %0 677 ANDX%b0\t%2, %0" 678 [(set_attr "type" "triple")] 679 ) 680 681 (define_insn "ior<mode>3" 682 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm") 683 (ior:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0") 684 (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))] 685 "" 686 "@ 687 BIS%x0%b0\t%2, %0 688 BISX%b0\t%2, %0" 689 [(set_attr "type" "triple")] 690 ) 691 692 (define_insn "xor<mode>3" 693 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm") 694 (xor:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0") 695 (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))] 696 "" 697 "@ 698 XOR%x0%b0\t%2, %0 699 XORX%b0\t%2, %0" 700 [(set_attr "type" "triple")] 701 ) 702 703 ;; Macro : XOR #~0, %0 704 (define_insn "one_cmpl<mode>2" 705 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYs,m") 706 (not:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")))] 707 "" 708 "@ 709 INV%x0%b0\t%0 710 INV%X0%b0\t%0" 711 [(set_attr "type" "double")] 712 ) 713 714 (define_insn "extendqihi2" 715 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYs,m") 716 (sign_extend:HI (match_operand:QI 1 "msp430_general_operand" "0,0")))] 717 "" 718 "@ 719 SXT%X0\t%0 720 SXT%X0\t%0" 721 [(set_attr "type" "single")] 722 ) 723 724 (define_insn "extendqipsi2" 725 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,m") 726 (sign_extend:PSI (match_operand:QI 1 "msp430_general_operand" "0,0")))] 727 "" 728 "@ 729 SXT\t%0 730 SXTX.A\t%0" 731 [(set_attr "type" "single") 732 (set_attr "extension" "none,x")] 733 ) 734 735 ;; ------------------------ 736 ;; ZERO EXTEND INSTRUCTIONS 737 ;; Byte-writes to registers clear bits 19:8 738 ;; * Byte-writes to memory do not affect bits 15:8 739 ;; Word-writes to registers clear bits 19:16 740 ;; PSImode writes to memory clear bits 15:4 of the second memory word 741 ;; We define all possible insns since that results in better code than if 742 ;; they are inferred. 743 ;; ------------------------ 744 745 (define_insn "zero_extendqihi2" 746 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYs,r,r,m") 747 (zero_extend:HI (match_operand:QI 1 "msp430_general_operand" "0,rYs,m,0")))] 748 "" 749 "@ 750 AND\t#0xff, %0 751 MOV.B\t%1, %0 752 MOV%X1.B\t%1, %0 753 AND%X0\t#0xff, %0" 754 [(set_attr "type" "double")] 755 ) 756 757 (define_insn "zero_extendqipsi2" 758 [(set (match_operand:PSI 0 "register_operand" "=r,r") 759 (zero_extend:PSI (match_operand:QI 1 "general_operand" "rYs,m")))] 760 "msp430x" 761 "@ 762 MOV.B\t%1, %0 763 MOV%X1.B\t%1, %0" 764 [(set_attr "type" "double")] 765 ) 766 767 (define_insn "zero_extendqisi2" 768 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r,r") 769 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,rm")))] 770 "" 771 "@ 772 CLR\t%H0 773 MOV%X1.B\t%1,%L0 { CLR\t%H0" 774 [(set_attr "extra_length" "2") 775 (set_attr "length_multiplier" "1,2") 776 (set_attr "type" "double")] 777 ) 778 779 (define_insn "zero_extendhipsi2" 780 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,r,m") 781 (zero_extend:PSI (match_operand:HI 1 "msp430_general_operand" "rYs,m,r")))] 782 "msp430x" 783 "@ 784 MOV.W\t%1, %0 785 MOV%X1\t%1, %0 786 MOVX.A\t%1, %0" 787 [(set_attr "type" "double")] 788 ) 789 790 (define_insn "zero_extendhisi2" 791 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm,r") 792 (zero_extend:SI (match_operand:HI 1 "general_operand" "0,r")))] 793 "" 794 "@ 795 MOV%X0.W\t#0,%H0 796 MOV.W\t%1,%L0 { MOV.W\t#0,%H0" 797 [(set_attr "length_multiplier" "1,2") 798 (set_attr "type" "double")] 799 ) 800 801 (define_insn "zero_extendhisipsi2" 802 [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r,r") 803 (subreg:PSI (zero_extend:SI (match_operand:HI 1 "general_operand" "0,r")) 0))] 804 "msp430x" 805 "@ 806 AND.W\t#-1,%0 807 MOV.W\t%1,%0" 808 [(set_attr "length" "4,2") 809 (set_attr "type" "double")] 810 ) 811 812 ; Nasty - we are sign-extending a 20-bit PSI value in one register into 813 ; two adjacent 16-bit registers to make an SI value. There is no MSP430X 814 ; instruction that will do this, so we push the 20-bit value onto the stack 815 ; and then pop it off as two 16-bit values. 816 ; 817 ; FIXME: The MSP430X documentation does not specify if zero-extension or 818 ; sign-extension happens when the 20-bit value is pushed onto the stack. 819 ; It is probably zero-extension, but if not this pattern will not work 820 ; when the PSI value is negative.. 821 ; 822 ; Note: using PUSHM.A #1 is two bytes smaller than using PUSHX.A.... 823 ; 824 ; Note: We use a + constraint on operand 0 as otherwise GCC gets confused 825 ; about extending a single PSI mode register into a pair of SImode registers 826 ; with the same starting register. It thinks that the upper register of 827 ; the pair is unused and so it can clobber it. Try compiling 20050826-2.c 828 ; at -O2 to see this. 829 830 ; FIXME we can use MOVA for r->m if m is &abs20 or z16(rdst) 831 (define_insn "zero_extendpsisi2" 832 [(set (match_operand:SI 0 "register_operand" "+r,m") 833 (zero_extend:SI (match_operand:PSI 1 "register_operand" "r,r")))] 834 "" 835 "@ 836 * if (REGNO (operands[1]) == SP_REGNO) \ 837 /* If the source register is the stack pointer, the value \ 838 stored in the stack slot will be the value *after* the \ 839 stack pointer has been decremented. So allow for that \ 840 here. */ \ 841 return \"PUSHM.A\t#1, %1 { ADDX.W\t#4, @r1 { POPX.W\t%L0 { POPX.W\t%H0 ; get stack pointer into %L0:%H0\"; \ 842 else \ 843 return \"PUSHM.A\t#1, %1 { POPX.W\t%L0 { POPX.W\t%H0 ; move pointer in %1 into reg-pair %L0:%H0\"; 844 MOVX.A %1, %0" 845 [(set (attr "length") 846 (cond [(match_test "REGNO (operands[1]) == SP_REGNO") 847 (const_int 18) 848 (eq_attr "alternative" "1") 849 (const_int 6)] 850 (const_int 10))) 851 (set_attr "type" "double")] 852 ) 853 854 ;; Below are unnamed insn patterns to catch pointer manipulation insns 855 ;; generated by combine. 856 ;; We get large code size bloat when a PSImode pointer is stored in 857 ;; memory, so we try to avoid that where possible and keep point manipulation 858 ;; between registers. 859 ; FIXME many of these should be unnnecessary once combine deals with 860 ; (sign_extend (zero_extend)) or (sign_extend (subreg)) BZ 91865. 861 862 ;; This is just another way of writing movqipsi/zero_extendqipsi 863 (define_insn "" 864 [(set (match_operand:PSI 0 "register_operand" "=r") 865 (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0)))] 866 "msp430x" 867 "MOV%X1.B\t%1, %0" 868 [(set_attr "type" "double")] 869 ) 870 871 (define_insn "" 872 [(set (match_operand:PSI 0 "register_operand" "=r,r") 873 (sign_extend:PSI (zero_extend:HI (match_operand:QI 1 "general_operand" "rYs,m"))))] 874 "msp430x" 875 "@ 876 MOV.B\t%1, %0 877 MOV%X1.B\t%1, %0" 878 [(set_attr "type" "double")] 879 ) 880 881 ;; The next three insns emit identical assembly code. 882 ;; They take a QImode and shift it in SImode. Only shift counts <= 8 883 ;; are handled since that is the simple case where the high 16-bits (i.e. the 884 ;; high register) are always 0. 885 (define_insn "" 886 [(set (match_operand:SI 0 "register_operand" "=r,r,r") 887 (ashift:SI (zero_extend:SI (match_operand:QI 1 "general_operand" "0,rm,rm")) 888 (match_operand:HI 2 "const_1_to_8_operand" "M,M,i")))] 889 "msp430x" 890 "@ 891 RLAM.W %2, %L0 { CLR %H0 892 MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0 893 MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0" 894 [(set_attr "length" "4,*,*") 895 (set_attr "extra_length" "0,4,6") 896 (set_attr "type" "double")] 897 ) 898 899 (define_insn "" 900 [(set (match_operand:SI 0 "register_operand" "=r,r,r") 901 (ashift:SI (zero_extend:SI (subreg:HI (match_operand:QI 1 "general_operand" "0,rm,rm") 0)) 902 (match_operand:HI 2 "const_1_to_8_operand" "M,M,i")))] 903 "msp430x" 904 "@ 905 RLAM.W %2, %L0 { CLR %H0 906 MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0 907 MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0" 908 [(set_attr "length" "4,*,*") 909 (set_attr "extra_length" "0,4,6") 910 (set_attr "type" "double")] 911 ) 912 913 ;; Same as above but with a NOP sign_extend round the subreg 914 (define_insn "" 915 [(set (match_operand:SI 0 "register_operand" "=r,r,r") 916 (ashift:SI (zero_extend:SI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "0,rm,rm") 0))) 917 (match_operand:HI 2 "const_1_to_8_operand" "M,M,i")))] 918 "msp430x" 919 "@ 920 RLAM.W %2, %L0 { CLR %H0 921 MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0 922 MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0" 923 [(set_attr "length" "4,*,*") 924 (set_attr "extra_length" "0,4,6") 925 (set_attr "type" "double")] 926 ) 927 928 (define_insn "" 929 [(set (match_operand:SI 0 "register_operand" "=r") 930 (zero_extend:SI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0))))] 931 "msp430x" 932 "MOV%X1.B %1, %L0 { CLR %H0" 933 [(set_attr "extra_length" "4") 934 (set_attr "type" "double")] 935 ) 936 937 (define_insn "" 938 [(set (match_operand:PSI 0 "register_operand" "=r,r,r") 939 (ashift:PSI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "0,rm,rm") 0)) 940 (match_operand:HI 2 "const_1_to_19_operand" "M,M,i")))] 941 "msp430x" 942 "@ 943 RLAM.W %2, %0 944 MOV%X1.B %1, %0 { RLAM.W %2, %0 945 MOV%X1.B %1, %0 { RPT %2 { RLAX.A %0" 946 [(set_attr "length" "2,*,*") 947 (set_attr "extra_length" "0,2,4") 948 (set_attr "type" "double")] 949 ) 950 ;; END msp430 pointer manipulation combine insn patterns 951 952 ;; Eliminate extraneous zero-extends mysteriously created by gcc. 953 (define_peephole2 954 [(set (match_operand:HI 0 "register_operand") 955 (zero_extend:HI (match_operand:QI 1 "general_operand"))) 956 (set (match_operand:HI 2 "register_operand") 957 (zero_extend:HI (match_operand:QI 3 "register_operand")))] 958 "REGNO (operands[0]) == REGNO (operands[2]) && REGNO (operands[2]) == REGNO (operands[3])" 959 [(set (match_dup 0) 960 (zero_extend:HI (match_dup 1)))] 961 ) 962 963 (define_insn "truncpsihi2" 964 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rm") 965 (truncate:HI (match_operand:PSI 1 "register_operand" "r")))] 966 "" 967 "MOVX\t%1, %0" 968 [(set_attr "extension" "m") 969 (set_attr "type" "double")] 970 ) 971 972 (define_insn "extendhisi2" 973 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r") 974 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))] 975 "" 976 { msp430x_extendhisi (operands, 0); return ""; } 977 [(set (attr "length") 978 (symbol_ref "msp430x_extendhisi (operands, 1)")) 979 (set_attr "type" "double")] 980 ) 981 982 (define_insn "extendhipsi2" 983 [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 984 (subreg:PSI (sign_extend:SI (match_operand:HI 1 "general_operand" "0")) 0))] 985 "msp430x" 986 "RLAM.A #4, %0 { RRAM.A #4, %0" 987 [(set_attr "length_multiplier" "2") 988 (set_attr "extension" "m") 989 (set_attr "type" "double")] 990 ) 991 992 ;; Look for cases where integer/pointer conversions are suboptimal due 993 ;; to missing patterns, despite us not having opcodes for these 994 ;; patterns. Doing these manually allows for alternate optimization 995 ;; paths. 996 997 (define_insn "extend_and_shift1_hipsi2" 998 [(set (subreg:SI (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 0) 999 (ashift:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0")) 1000 (const_int 1)))] 1001 "msp430x" 1002 "RLAM.A #4, %0 { RRAM.A #3, %0" 1003 [(set_attr "length_multiplier" "2") 1004 (set_attr "extension" "m") 1005 (set_attr "type" "double")] 1006 ) 1007 1008 (define_insn "extend_and_shift2_hipsi2" 1009 [(set (subreg:SI (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 0) 1010 (ashift:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0")) 1011 (const_int 2)))] 1012 "msp430x" 1013 "RLAM.A #4, %0 { RRAM.A #2, %0" 1014 [(set_attr "length_multiplier" "2") 1015 (set_attr "extension" "m") 1016 (set_attr "type" "double")] 1017 ) 1018 1019 ;; We also need to be able to sign-extend pointer types (eg ptrdiff_t). 1020 ;; Since (we assume) pushing a 20-bit value onto the stack zero-extends 1021 ;; it, we use a different method here. 1022 1023 (define_insn "extendpsisi2" 1024 [(set (match_operand:SI 0 "register_operand" "=r") 1025 (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))] 1026 "msp430x" 1027 "* 1028 /* The intention here is that we copy the bottom 16-bits of 1029 %1 into %L0 (zeroing the top four bits). Then we copy the 1030 entire 20-bits of %1 into %H0 and then arithmetically shift 1031 it right by 16 bits, to get the top four bits of the pointer 1032 sign-extended in %H0. */ 1033 if (REGNO (operands[0]) == REGNO (operands[1])) 1034 return \"MOVX.A\t%1, %H0 { MOV.W\t%1, %L0 { RPT\t#16 { RRAX.A\t%H0 ; sign extend pointer in %1 into %L0:%H0\"; 1035 else 1036 return \"MOV.W\t%1, %L0 { MOVX.A\t%1, %H0 { RPT\t#16 { RRAX.A\t%H0 ; sign extend pointer in %1 into %L0:%H0\"; 1037 " 1038 [(set_attr "length" "10") 1039 (set_attr "type" "double")] 1040 ) 1041 1042 ; See the movsipsi2 pattern above for another way that GCC performs this 1043 ; conversion. 1044 (define_insn "truncsipsi2" 1045 [(set (match_operand:PSI 0 "register_operand" "=r") 1046 (truncate:PSI (match_operand:SI 1 "register_operand" "r")))] 1047 "" 1048 "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A\t#1, %L0" 1049 [(set_attr "length" "6") 1050 (set_attr "type" "single")] 1051 ) 1052 1053 ;;------------------------------------------------------------ 1054 ;; Shift Functions 1055 1056 ;; Note: We do not use the RPT ... SHIFT instruction sequence 1057 ;; when the repeat count is in a register, because even though RPT 1058 ;; accepts counts in registers, it does not work if the count is 1059 ;; zero, and the actual count in the register has to be one less 1060 ;; than the required number of iterations. We could encode a 1061 ;; seqeunce like this: 1062 ;; 1063 ;; bit #0xf, Rn 1064 ;; bz 1f 1065 ;; dec Rn 1066 ;; rpt Rn 1067 ;; <shift> Rm 1068 ;; inc Rn 1069 ;; 1: 1070 ;; 1071 ;; But is longer than calling a helper function, and we are mostly 1072 ;; concerned with code size. FIXME: Maybe enable a sequence like 1073 ;; this at -O3 and above ? 1074 ;; 1075 ;; Note - we ignore shift counts of less than one or more than 15. 1076 ;; This is permitted by the ISO C99 standard as such shifts result 1077 ;; in "undefined" behavior. [6.5.7 (3)] 1078 ;; 1079 ;; We avoid emitting insns in msp430_expand_shift, since we would have to handle 1080 ;; many extra cases such as op0 != op1, or, op0 or op1 in memory. Instead we 1081 ;; let reload coerce op0 and op1 into the same register. 1082 1083 (define_expand "<shift_insn><mode>3" 1084 [(set (match_operand:HDI 0 "msp430_general_dst_nonv_operand") 1085 (any_shift:HDI (match_operand:HDI 1 "general_operand") 1086 (match_operand:HDI 2 "general_operand")))] 1087 "" 1088 { 1089 if (msp430_expand_shift (<CODE>, <MODE>mode, operands)) 1090 DONE; 1091 /* Otherwise, fallthrough. */ 1092 } 1093 ) 1094 1095 ;; All 430 HImode constant shifts 1096 (define_insn "<shift_insn>hi3_430" 1097 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=rm") 1098 (any_shift:HI (match_operand:HI 1 "general_operand" "0") 1099 (match_operand:HI 2 "const_int_operand" "n")))] 1100 "!msp430x" 1101 "* msp430_output_asm_shift_insns (<CODE>, HImode, operands, false); return \"\";" 1102 [(set (attr "length") 1103 (symbol_ref "msp430_output_asm_shift_insns (<CODE>, HImode, operands, true)")) 1104 (set_attr "type" "single")] 1105 ) 1106 1107 ;; All 430 and 430X SImode constant shifts 1108 (define_insn "<shift_insn>si3_const" 1109 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm") 1110 (any_shift:SI (match_operand:SI 1 "general_operand" "0") 1111 (match_operand:SI 2 "const_int_operand" "n")))] 1112 "" 1113 "* msp430_output_asm_shift_insns (<CODE>, SImode, operands, false); return \"\";" 1114 [(set (attr "length") 1115 (symbol_ref "msp430_output_asm_shift_insns (<CODE>, SImode, operands, true)")) 1116 (set_attr "type" "single")] 1117 ) 1118 1119 (define_insn "ashl<mode>3_430x" 1120 [(set (match_operand:HPSI 0 "msp430_general_dst_nonv_operand" "=r,r,r,r") 1121 (ashift:HPSI (match_operand:HPSI 1 "general_operand" "0 ,0,0,0") 1122 (match_operand:HPSI 2 "const_int_operand" "M ,P,K,i")))] 1123 "msp430x" 1124 "@ 1125 RLAM%b0\t%2, %0 1126 RPT\t%2 { RLAX%b0\t%0 1127 RPT\t#16 { RLAX%b0\t%0 { RPT\t%W2 { RLAX%b0\t%0 1128 # undefined behavior left shift of %1 by %2" 1129 [(set_attr "length" "2,4,8,0") 1130 (set_attr "type" "single")] 1131 ) 1132 1133 (define_insn "ashr<mode>3_430x" 1134 [(set (match_operand:HPSI 0 "msp430_general_dst_nonv_operand" "=r,r,r,r") 1135 (ashiftrt:HPSI (match_operand:HPSI 1 "general_operand" "0,0,0,0") 1136 (match_operand:HPSI 2 "const_int_operand" "M,P,K,i")))] 1137 "msp430x" 1138 "@ 1139 RRAM%b0\t%2, %0 1140 RPT\t%2 { RRAX%b0\t%0 1141 RPT\t#16 { RRAX%b0\t%0 { RPT\t%W2 { RRAX%b0\t%0 1142 # undefined behavior arithmetic right shift of %1 by %2" 1143 [(set_attr "length" "2,4,8,0") 1144 (set_attr "type" "single")] 1145 ) 1146 1147 (define_insn "lshr<mode>3_430x" 1148 [(set (match_operand:HPSI 0 "msp430_general_dst_nonv_operand" "=r,r,r,r") 1149 (lshiftrt:HPSI (match_operand:HPSI 1 "general_operand" "0,0,0,0") 1150 (match_operand:HPSI 2 "const_int_operand" "M,P,K,i")))] 1151 "msp430x" 1152 "@ 1153 RRUM%b0\t%2, %0 1154 RPT\t%2 { RRUX%b0\t%0 1155 RPT\t#16 { RRUX%b0\t%0 { RPT\t%W2 { RRUX%b0\t%0 1156 # undefined behavior logical right shift of %1 by %2" 1157 [(set_attr "length" "2,4,8,0") 1158 (set_attr "type" "single")] 1159 ) 1160 1161 ;;------------------------------------------------------------ 1162 ;; Function Entry/Exit 1163 1164 (define_expand "prologue" 1165 [(const_int 0)] 1166 "" 1167 "msp430_expand_prologue (); DONE;" 1168 ) 1169 1170 (define_expand "epilogue" 1171 [(const_int 0)] 1172 "" 1173 "msp430_expand_epilogue (0); DONE;" 1174 ) 1175 1176 (define_insn "epilogue_helper" 1177 [(set (pc) 1178 (unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER)) 1179 (return)] 1180 "!msp430x" 1181 "BR%Q0\t#__mspabi_func_epilog_%J0" 1182 [(set_attr "length" "2")] 1183 ) 1184 1185 (define_insn "prologue_start_marker" 1186 [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)] 1187 "" 1188 "; start of prologue" 1189 [(set_attr "length" "0")] 1190 ) 1191 1192 (define_insn "prologue_end_marker" 1193 [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)] 1194 "" 1195 "; end of prologue" 1196 [(set_attr "length" "0")] 1197 ) 1198 1199 (define_insn "epilogue_start_marker" 1200 [(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)] 1201 "" 1202 "; start of epilogue" 1203 [(set_attr "length" "0")] 1204 ) 1205 1206 ;; This makes the linker add a call to exit() after the call to main() 1207 ;; in crt0 1208 (define_insn "msp430_refsym_need_exit" 1209 [(unspec_volatile [(const_int 0)] UNS_REFSYM_NEED_EXIT)] 1210 "" 1211 ".refsym\t__crt0_call_exit" 1212 [(set_attr "length" "0")] 1213 ) 1214 1215 ;;------------------------------------------------------------ 1216 ;; Jumps 1217 1218 (define_expand "call" 1219 [(call:HI (match_operand 0 "") 1220 (match_operand 1 ""))] 1221 "" 1222 "" 1223 ) 1224 1225 (define_insn "call_internal" 1226 [(call (mem:HI (match_operand 0 "general_operand" "rYci")) 1227 (match_operand 1 ""))] 1228 "" 1229 "CALL%Q0\t%0" 1230 [(set_attr "extension" "none") 1231 (set_attr "type" "single")] 1232 ) 1233 1234 (define_expand "call_value" 1235 [(set (match_operand 0 "register_operand") 1236 (call:HI (match_operand 1 "general_operand") 1237 (match_operand 2 "")))] 1238 "" 1239 "" 1240 ) 1241 1242 (define_insn "call_value_internal" 1243 [(set (match_operand 0 "register_operand" "=r") 1244 (call (mem:HI (match_operand 1 "general_operand" "rYci")) 1245 (match_operand 2 "")))] 1246 "" 1247 "CALL%Q0\t%1" 1248 [(set_attr "extension" "none") 1249 (set_attr "type" "single")] 1250 ) 1251 1252 (define_insn "msp430_return" 1253 [(return)] 1254 "" 1255 { return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); } 1256 [(set_attr "length" "2")] 1257 ) 1258 1259 ;; This pattern is NOT, as expected, a return pattern. It's called 1260 ;; before reload and must only store its operands, and emit a 1261 ;; placeholder where the epilog needs to be. AFTER reload, the 1262 ;; placeholder should get expanded into a regular-type epilogue that 1263 ;; also does the EH return. 1264 (define_expand "eh_return" 1265 [(match_operand:HI 0 "")] 1266 "" 1267 "msp430_expand_eh_return (operands[0]); 1268 emit_jump_insn (gen_msp430_eh_epilogue ()); 1269 emit_barrier (); 1270 DONE;" 1271 ) 1272 1273 ;; This is the actual EH epilogue. We emit it in the pattern above, 1274 ;; before reload, and convert it to a real epilogue after reload. 1275 (define_insn_and_split "msp430_eh_epilogue" 1276 [(eh_return)] 1277 "" 1278 "#" 1279 "reload_completed" 1280 [(const_int 0)] 1281 "msp430_expand_epilogue (1); DONE;" 1282 [(set_attr "length" "40")] 1283 ) 1284 1285 (define_insn "jump" 1286 [(set (pc) 1287 (label_ref (match_operand 0 "" "")))] 1288 "" 1289 "BR%Q0\t#%l0" 1290 [(set_attr "length" "4")] 1291 ) 1292 1293 ;; FIXME: GCC currently (8/feb/2013) cannot handle symbol_refs 1294 ;; in indirect jumps (cf gcc.c-torture/compile/991213-3.c). 1295 (define_insn "indirect_jump" 1296 [(set (pc) 1297 (match_operand 0 "nonimmediate_operand" "rYl"))] 1298 "" 1299 "BR%Q0\t%0" 1300 [(set (attr "length") 1301 (if_then_else (match_operand 0 "register_operand" "") 1302 (const_int 2) 1303 (const_int 4)))] 1304 ) 1305 1306 ;;------------------------------------------------------------ 1307 ;; Various Conditionals 1308 1309 (define_expand "cbranch<mode>4" 1310 [(parallel [(set (pc) (if_then_else 1311 (match_operator 0 "" 1312 [(match_operand:QHI 1 "msp430_general_dst_nonv_operand") 1313 (match_operand:QHI 2 "general_operand")]) 1314 (label_ref (match_operand 3 "" "")) 1315 (pc))) 1316 (clobber (reg:BI CARRY))] 1317 )] 1318 "" 1319 "msp430_fixup_compare_operands (<MODE>mode, operands);" 1320 ) 1321 1322 (define_insn "cbranchpsi4_real" 1323 [(set (pc) (if_then_else 1324 (match_operator 0 "msp430_cmp_operator" 1325 [(match_operand:PSI 1 "msp430_general_dst_nonv_operand" "r,rYs,rm") 1326 (match_operand:PSI 2 "general_operand" "rLs,rYsi,rmi")]) 1327 (label_ref (match_operand 3 "" "")) 1328 (pc))) 1329 (clobber (reg:BI CARRY)) 1330 ] 1331 "" 1332 "@ 1333 CMP%Q0\t%2, %1 { J%0\t%l3 1334 CMPX.A\t%2, %1 { J%0\t%l3 1335 CMPX.A\t%2, %1 { J%0\t%l3" 1336 [(set_attr "extra_length" "2") 1337 (set_attr "type" "cmp")] 1338 ) 1339 1340 (define_insn "cbranchqi4_real" 1341 [(set (pc) (if_then_else 1342 (match_operator 0 "msp430_cmp_operator" 1343 [(match_operand:QI 1 "msp430_general_dst_nonv_operand" "rYsYx,rm") 1344 (match_operand:QI 2 "general_operand" "rYsYxi,rmi")]) 1345 (label_ref (match_operand 3 "" "")) 1346 (pc))) 1347 (clobber (reg:BI CARRY)) 1348 ] 1349 "" 1350 "@ 1351 CMP.B\t%2, %1 { J%0\t%l3 1352 CMPX.B\t%2, %1 { J%0\t%l3" 1353 [(set_attr "extra_length" "2") 1354 (set_attr "type" "cmp")] 1355 ) 1356 1357 (define_insn "cbranchhi4_real" 1358 [(set (pc) (if_then_else 1359 (match_operator 0 "msp430_cmp_operator" 1360 [(match_operand:HI 1 "msp430_general_dst_nonv_operand" "rYsYx,rm") 1361 (match_operand:HI 2 "general_operand" "rYsYxi,rmi")]) 1362 (label_ref (match_operand 3 "" "")) 1363 (pc))) 1364 (clobber (reg:BI CARRY)) 1365 ] 1366 "" 1367 "@ 1368 CMP.W\t%2, %1 { J%0\t%l3 1369 CMPX.W\t%2, %1 { J%0\t%l3" 1370 [(set_attr "extra_length" "2") 1371 (set_attr "type" "cmp")] 1372 ) 1373 1374 (define_insn "cbranchpsi4_reversed" 1375 [(set (pc) (if_then_else 1376 (match_operator 0 "msp430_reversible_cmp_operator" 1377 [(match_operand:PSI 1 "general_operand" "rLs,rYsi,rmi") 1378 (match_operand:PSI 2 "msp430_general_dst_nonv_operand" "r,rYs,rm")]) 1379 (label_ref (match_operand 3 "" "")) 1380 (pc))) 1381 (clobber (reg:BI CARRY)) 1382 ] 1383 "" 1384 "@ 1385 CMP%Q0\t%1, %2 { J%R0\t%l3 1386 CMPX.A\t%1, %2 { J%R0\t%l3 1387 CMPX.A\t%1, %2 { J%R0\t%l3" 1388 [(set_attr "extra_length" "2") 1389 (set_attr "type" "cmp")] 1390 ) 1391 1392 (define_insn "cbranchqi4_reversed" 1393 [(set (pc) (if_then_else 1394 (match_operator 0 "msp430_reversible_cmp_operator" 1395 [(match_operand:QI 1 "general_operand" "rYsYxi,rmi") 1396 (match_operand:QI 2 "msp430_general_dst_nonv_operand" "rYsYx,rm")]) 1397 (label_ref (match_operand 3 "" "")) 1398 (pc))) 1399 (clobber (reg:BI CARRY)) 1400 ] 1401 "" 1402 "@ 1403 CMP.B\t%1, %2 { J%R0\t%l3 1404 CMPX.B\t%1, %2 { J%R0\t%l3" 1405 [(set_attr "extra_length" "2") 1406 (set_attr "type" "cmp")] 1407 ) 1408 1409 (define_insn "cbranchhi4_reversed" 1410 [(set (pc) (if_then_else 1411 (match_operator 0 "msp430_reversible_cmp_operator" 1412 [(match_operand:HI 1 "general_operand" "rYsYxi,rmi") 1413 (match_operand:HI 2 "msp430_general_dst_nonv_operand" "rYsYx,rm")]) 1414 (label_ref (match_operand 3 "" "")) 1415 (pc))) 1416 (clobber (reg:BI CARRY)) 1417 ] 1418 "" 1419 "@ 1420 CMP.W\t%1, %2 { J%R0\t%l3 1421 CMPX.W\t%1, %2 { J%R0\t%l3" 1422 [(set_attr "extra_length" "2") 1423 (set_attr "type" "cmp")] 1424 ) 1425 1426 (define_insn "*bitbranch<mode>4" 1427 [(set (pc) (if_then_else 1428 (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm") 1429 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi")) 1430 (const_int 0)) 1431 (label_ref (match_operand 2 "" "")) 1432 (pc))) 1433 (clobber (reg:BI CARRY)) 1434 ] 1435 "" 1436 "@ 1437 BIT%x0%b0\t%1, %0 { JNE\t%l2 1438 BITX%b0\t%1, %0 { JNE\t%l2" 1439 [(set_attr "extra_length" "2") 1440 (set_attr "type" "double")] 1441 ) 1442 1443 (define_insn "*bitbranch<mode>4" 1444 [(set (pc) (if_then_else 1445 (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm") 1446 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi")) 1447 (const_int 0)) 1448 (label_ref (match_operand 2 "" "")) 1449 (pc))) 1450 (clobber (reg:BI CARRY)) 1451 ] 1452 "" 1453 "@ 1454 BIT%x0%b0\t%1, %0 { JEQ\t%l2 1455 BITX%b0\t%1, %0 { JEQ\t%l2" 1456 [(set_attr "extra_length" "2") 1457 (set_attr "type" "double")] 1458 ) 1459 1460 (define_insn "*bitbranch<mode>4" 1461 [(set (pc) (if_then_else 1462 (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm") 1463 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi")) 1464 (const_int 0)) 1465 (pc) 1466 (label_ref (match_operand 2 "" "")))) 1467 (clobber (reg:BI CARRY)) 1468 ] 1469 "" 1470 "@ 1471 BIT%x0%b0\t%1, %0 { JNE\t%l2 1472 BITX%b0\t%1, %0 { JNE\t%l2" 1473 [(set_attr "extra_length" "2") 1474 (set_attr "type" "double")] 1475 ) 1476 1477 (define_insn "*bitbranch<mode>4" 1478 [(set (pc) (if_then_else 1479 (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm") 1480 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi")) 1481 (const_int 0)) 1482 (pc) 1483 (label_ref (match_operand 2 "" "")))) 1484 (clobber (reg:BI CARRY)) 1485 ] 1486 "" 1487 "@ 1488 BIT%x0%b0\t%1, %0 { JEQ\t%l2 1489 BITX%b0\t%1, %0 { JEQ\t%l2" 1490 [(set_attr "extra_length" "2") 1491 (set_attr "type" "double")] 1492 ) 1493 1494 ;;------------------------------------------------------------ 1495 ;; zero-extract versions of the above 1496 1497 (define_insn "*bitbranch<mode>4_z" 1498 [(set (pc) (if_then_else 1499 (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rYs,rm") 1500 (const_int 1) 1501 (match_operand 1 "const_0_to_15_operand" "i,i")) 1502 (const_int 0)) 1503 (label_ref (match_operand 2 "" "")) 1504 (pc))) 1505 (clobber (reg:BI CARRY)) 1506 ] 1507 "" 1508 "@ 1509 BIT%x0%b0\t%p1, %0 { JNE\t%l2 1510 BIT%X0%b0\t%p1, %0 { JNE\t%l2" 1511 [(set_attr "extra_length" "2") 1512 (set_attr "type" "double")] 1513 ) 1514 1515 (define_insn "*bitbranch<mode>4_z" 1516 [(set (pc) (if_then_else 1517 (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm") 1518 (const_int 1) 1519 (match_operand 1 "const_0_to_15_operand" "i")) 1520 (const_int 0)) 1521 (label_ref (match_operand 2 "" "")) 1522 (pc))) 1523 (clobber (reg:BI CARRY)) 1524 ] 1525 "" 1526 "BIT%X0%b0\t%p1, %0 { JEQ\t%l2" 1527 [(set_attr "extra_length" "2") 1528 (set_attr "type" "double")] 1529 ) 1530 1531 (define_insn "*bitbranch<mode>4_z" 1532 [(set (pc) (if_then_else 1533 (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm") 1534 (const_int 1) 1535 (match_operand 1 "const_0_to_15_operand" "i")) 1536 (const_int 0)) 1537 (pc) 1538 (label_ref (match_operand 2 "" "")))) 1539 (clobber (reg:BI CARRY)) 1540 ] 1541 "" 1542 "BIT%X0%b0\t%p1, %0 { JNE\t%l2" 1543 [(set_attr "extra_length" "2") 1544 (set_attr "type" "double")] 1545 ) 1546 1547 (define_insn "*bitbranch<mode>4_z" 1548 [(set (pc) (if_then_else 1549 (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm") 1550 (const_int 1) 1551 (match_operand 1 "const_0_to_15_operand" "i")) 1552 (const_int 0)) 1553 (pc) 1554 (label_ref (match_operand 2 "" "")))) 1555 (clobber (reg:BI CARRY)) 1556 ] 1557 "" 1558 "BIT%X0%b0\t%p1, %0 { JEQ\t%l2" 1559 [(set_attr "extra_length" "2") 1560 (set_attr "type" "double")] 1561 ) 1562 1563 ;;------------------------------------------------------------ 1564 ;; Misc 1565 1566 (define_insn "nop" 1567 [(const_int 0)] 1568 "1" 1569 "NOP" 1570 [(set_attr "length" "2")] 1571 ) 1572 1573 (define_insn "disable_interrupts" 1574 [(unspec_volatile [(const_int 0)] UNS_DINT)] 1575 "" 1576 "DINT \; NOP" 1577 [(set_attr "length" "2")] 1578 ) 1579 1580 (define_insn "enable_interrupts" 1581 [(unspec_volatile [(const_int 0)] UNS_EINT)] 1582 "" 1583 "EINT" 1584 [(set_attr "length" "2")] 1585 ) 1586 1587 (define_insn "push_intr_state" 1588 [(unspec_volatile [(const_int 0)] UNS_PUSH_INTR)] 1589 "" 1590 "PUSH\tSR" 1591 [(set_attr "length" "2")] 1592 ) 1593 1594 (define_insn "pop_intr_state" 1595 [(unspec_volatile [(const_int 0)] UNS_POP_INTR)] 1596 "" 1597 "POP\tSR" 1598 [(set_attr "length" "2")] 1599 ) 1600 1601 ;; Clear bits in the copy of the status register that is currently 1602 ;; saved on the stack at the top of the interrupt handler. 1603 (define_insn "bic_SR" 1604 [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIC_SR)] 1605 "" 1606 "BIC.W\t%0, %O0(SP)" 1607 [(set_attr "type" "single") 1608 (set_attr "extra_length" "2")] 1609 ) 1610 1611 ;; Set bits in the copy of the status register that is currently 1612 ;; saved on the stack at the top of the interrupt handler. 1613 (define_insn "bis_SR" 1614 [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIS_SR)] 1615 "" 1616 "BIS.W\t%0, %O0(SP)" 1617 [(set_attr "type" "single") 1618 (set_attr "extra_length" "2")] 1619 ) 1620 1621 ;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int))) 1622 ;; very late on in the compilation and not splitting it into separate 1623 ;; instructions, so we provide a pattern to support it here. 1624 (define_insn "andneghi3" 1625 [(set (match_operand:HI 0 "register_operand" "=r,r") 1626 (and:HI (neg:HI (match_operand:HI 1 "general_operand" "0,rm")) 1627 (match_operand 2 "immediate_operand" "n,n")))] 1628 "" 1629 "@ 1630 INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0 1631 MOV%X1.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0" 1632 [(set_attr "length" "12,14") 1633 (set_attr "type" "double")] 1634 ) 1635 1636 1637 (define_insn "delay_cycles_start" 1638 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] 1639 UNS_DELAY_START)] 1640 "" 1641 "; Begin %J0 cycle delay" 1642 [(set_attr "length" "0")] 1643 ) 1644 1645 (define_insn "delay_cycles_end" 1646 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] 1647 UNS_DELAY_END)] 1648 "" 1649 "; End %J0 cycle delay" 1650 ) 1651 1652 (define_insn "delay_cycles_32" 1653 [(unspec_volatile [(match_operand 0 "immediate_operand" "i") 1654 (match_operand 1 "immediate_operand" "i") 1655 ] UNS_DELAY_32)] 1656 "" 1657 "PUSH r13 1658 PUSH r14 1659 MOV.W %A0, r13 1660 MOV.W %B0, r14 1661 1: SUB.W #1, r13 1662 SUBC.W #0, r14 1663 JNE 1b 1664 TST.W r13 1665 JNE 1b 1666 POP r14 1667 POP r13" 1668 [(set_attr "length" "32")] 1669 ) 1670 1671 (define_insn "delay_cycles_32x" 1672 [(unspec_volatile [(match_operand 0 "immediate_operand" "i") 1673 (match_operand 1 "immediate_operand" "i") 1674 ] UNS_DELAY_32X)] 1675 "" 1676 "PUSHM.A #2,r14 1677 MOV.W %A0, r13 1678 MOV.W %B0, r14 1679 1: SUB.W #1, r13 1680 SUBC.W #0, r14 1681 JNE 1b 1682 TST.W r13 1683 JNE 1b 1684 POPM.A #2,r14" 1685 [(set_attr "length" "28")] 1686 ) 1687 1688 (define_insn "delay_cycles_16" 1689 [(unspec_volatile [(match_operand 0 "immediate_operand" "i") 1690 (match_operand 1 "immediate_operand" "i") 1691 ] UNS_DELAY_16)] 1692 "" 1693 "PUSH r13 1694 MOV.W %0, r13 1695 1: SUB.W #1, r13 1696 JNE 1b 1697 POP r13" 1698 [(set_attr "length" "14")] 1699 ) 1700 1701 (define_insn "delay_cycles_16x" 1702 [(unspec_volatile [(match_operand 0 "immediate_operand" "i") 1703 (match_operand 1 "immediate_operand" "i") 1704 ] UNS_DELAY_16X)] 1705 "" 1706 "PUSHM.A #1,r13 1707 MOV.W %0, r13 1708 1: SUB.W #1, r13 1709 JNE 1b 1710 POPM.A #1,r13" 1711 [(set_attr "length" "14")] 1712 ) 1713 1714 (define_insn "delay_cycles_2" 1715 [(unspec_volatile [(const_int 0) ] UNS_DELAY_2)] 1716 "" 1717 "JMP .+2" 1718 [(set_attr "length" "2")] 1719 ) 1720 1721 (define_insn "delay_cycles_1" 1722 [(unspec_volatile [(const_int 0) ] UNS_DELAY_1)] 1723 "" 1724 "NOP" 1725 [(set_attr "length" "2")] 1726 ) 1727 1728 (define_expand "mulhi3" 1729 [(set (match_operand:HI 0 "register_operand" "=r") 1730 (mult:HI (match_operand:HI 1 "register_operand" "%0") 1731 (match_operand:HI 2 "register_operand" "r")))] 1732 "msp430_has_hwmult ()" 1733 { 1734 msp430_expand_helper (operands, "__mspabi_mpyi", false); 1735 DONE; 1736 } 1737 ) 1738 1739 (define_expand "mulsi3" 1740 [(set (match_operand:SI 0 "register_operand" "=r") 1741 (mult:SI (match_operand:SI 1 "register_operand" "%0") 1742 (match_operand:SI 2 "register_operand" "r")))] 1743 "msp430_has_hwmult ()" 1744 { 1745 msp430_expand_helper (operands, "__mspabi_mpyl", false); 1746 DONE; 1747 } 1748 ) 1749 1750 ; libgcc helper functions for widening multiplication aren't currently 1751 ; generated by gcc, so we can't catch them later and map them to the mspabi 1752 ; functions. 1753 ; We catch the patterns here and either generate a call to the helper function, 1754 ; or emit the hardware multiply instruction sequence inline. 1755 ; 1756 ; If we don't have hardware multiply support, it will generally be slower and 1757 ; result in larger code to call the mspabi library function to perform the 1758 ; widening multiplication than just leaving GCC to widen the arguments itself. 1759 1760 (define_expand "mulhisi3" 1761 [(set (match_operand:SI 0 "register_operand" "=r") 1762 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) 1763 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] 1764 "msp430_has_hwmult ()" 1765 { 1766 /* Leave the other case for the inline insn. */ 1767 if (!(optimize > 2 && msp430_has_hwmult ())) 1768 { 1769 msp430_expand_helper (operands, "__mspabi_mpysl", false); 1770 DONE; 1771 } 1772 } 1773 ) 1774 1775 (define_expand "umulhisi3" 1776 [(set (match_operand:SI 0 "register_operand" "=r") 1777 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0")) 1778 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))] 1779 "msp430_has_hwmult ()" 1780 { 1781 /* Leave the other case for the inline insn. */ 1782 if (!(optimize > 2 && msp430_has_hwmult ())) 1783 { 1784 msp430_expand_helper (operands, "__mspabi_mpyul", false); 1785 DONE; 1786 } 1787 } 1788 ) 1789 1790 (define_expand "mulsidi3" 1791 [(set (match_operand:DI 0 "register_operand" "=r") 1792 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) 1793 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 1794 "msp430_has_hwmult ()" 1795 { 1796 /* Leave the other case for the inline insn. */ 1797 if (!(optimize > 2 && msp430_has_hwmult ())) 1798 { 1799 msp430_expand_helper (operands, "__mspabi_mpysll", false); 1800 DONE; 1801 } 1802 } 1803 ) 1804 1805 (define_expand "umulsidi3" 1806 [(set (match_operand:DI 0 "register_operand" "=r") 1807 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) 1808 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 1809 "msp430_has_hwmult ()" 1810 { 1811 /* Leave the other case for the inline insn. */ 1812 if (!(optimize > 2 && msp430_has_hwmult ())) 1813 { 1814 msp430_expand_helper (operands, "__mspabi_mpyull", false); 1815 DONE; 1816 } 1817 } 1818 ) 1819 1820 1821 (define_insn "*mulhisi3_inline" 1822 [(set (match_operand:SI 0 "register_operand" "=r") 1823 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) 1824 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] 1825 "optimize > 2 && msp430_has_hwmult ()" 1826 "* 1827 if (msp430_use_f5_series_hwmult ()) 1828 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x04C2 { MOV.W %2, &0x04C8 { MOV.W &0x04CA, %L0 { MOV.W &0x04CC, %H0 { POP.W sr\"; 1829 else 1830 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0132 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\"; 1831 " 1832 [(set_attr "length" "24")] 1833 ) 1834 1835 (define_insn "*umulhisi3_inline" 1836 [(set (match_operand:SI 0 "register_operand" "=r") 1837 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0")) 1838 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))] 1839 "optimize > 2 && msp430_has_hwmult ()" 1840 "* 1841 if (msp430_use_f5_series_hwmult ()) 1842 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x04C0 { MOV.W %2, &0x04C8 { MOV.W &0x04CA, %L0 { MOV.W &0x04CC, %H0 { POP.W sr\"; 1843 else 1844 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0130 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\"; 1845 " 1846 [(set_attr "length" "24")] 1847 ) 1848 1849 (define_insn "*mulsidi3_inline" 1850 [(set (match_operand:DI 0 "register_operand" "=r") 1851 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) 1852 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 1853 "optimize > 2 && msp430_has_hwmult ()" 1854 "* 1855 if (msp430_use_f5_series_hwmult ()) 1856 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x04D4 { MOV.W %H1, &0x04D6 { MOV.W %L2, &0x04E0 { MOV.W %H2, &0x04E2 { MOV.W &0x04E4, %A0 { MOV.W &0x04E6, %B0 { MOV.W &0x04E8, %C0 { MOV.W &0x04EA, %D0 { POP.W sr\"; 1857 else 1858 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0144 { MOV.W %H1, &0x0146 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\"; 1859 " 1860 [(set_attr "length" "40")] 1861 ) 1862 1863 (define_insn "*umulsidi3_inline" 1864 [(set (match_operand:DI 0 "register_operand" "=r") 1865 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) 1866 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 1867 "optimize > 2 && msp430_has_hwmult ()" 1868 "* 1869 if (msp430_use_f5_series_hwmult ()) 1870 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x04D0 { MOV.W %H1, &0x04D2 { MOV.W %L2, &0x04E0 { MOV.W %H2, &0x04E2 { MOV.W &0x04E4, %A0 { MOV.W &0x04E6, %B0 { MOV.W &0x04E8, %C0 { MOV.W &0x04EA, %D0 { POP.W sr\"; 1871 else 1872 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0140 { MOV.W %H1, &0x0142 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\"; 1873 " 1874 [(set_attr "length" "40")] 1875 ) 1876